Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 //* -*-Mode: c++;-*- (Tell emacs to use c++ mode) */ 00037 // 00038 // ==================================================================== 00039 // ==================================================================== 00040 // 00041 // $Author: 00042 // $Source: 00043 // 00044 // Revision history: 00045 // 4-Sept-97 - Original Version 00046 // 00047 // Description: 00048 // 00049 // This module contains the array sections utils needed by main IPA. 00050 // 00051 // ==================================================================== 00052 // ==================================================================== 00053 00054 #include <sys/types.h> 00055 #include <alloca.h> 00056 00057 #include "defs.h" 00058 #include "cxx_memory.h" 00059 #include "soe.h" 00060 #include "ipa_section.h" 00061 #include "ipa_lno_util.h" 00062 00063 #ifndef IPA_SUMMARY 00064 INT IPA_Ivar_Global_Count; 00065 INT IPA_Ivar_Count; 00066 mINT32 00067 SYSTEM_OF_EQUATIONS::_work_cols; 00068 mINT32 00069 SYSTEM_OF_EQUATIONS::_work_rows_eq; 00070 mINT32 00071 SYSTEM_OF_EQUATIONS::_work_rows; 00072 MEM_POOL* 00073 MAT<int>::_default_pool; 00074 #endif 00075 00076 //========================================================================= 00077 // free the terms 00078 //========================================================================= 00079 void 00080 LINEX::Free_terms() 00081 { 00082 _larray.Free_array(); 00083 _larray.Resetidx(); 00084 } 00085 00086 //========================================================================= 00087 // reset the node fields 00088 //========================================================================= 00089 void 00090 PROJECTED_NODE::Reset_node() 00091 { 00092 LINEX *l; 00093 if (l = Get_upper_linex()) 00094 l->Free_terms(); 00095 if (l = Get_lower_linex()) 00096 l->Free_terms(); 00097 if (l = Get_step_linex()) 00098 l->Free_terms(); 00099 if (l = Get_segment_length_linex()) 00100 l->Free_terms(); 00101 if (l = Get_segment_stride_linex()) 00102 l->Free_terms(); 00103 00104 Set_flags(0); 00105 } 00106 00107 //========================================================================= 00108 // Set_constant_linexs. Set the linexs to contain constant values 00109 //========================================================================= 00110 void 00111 PROJECTED_NODE::Set_constant_linexs(INT32 upper, 00112 INT32 lower, 00113 INT32 step, 00114 INT32 segment_length, 00115 INT32 segment_stride) 00116 { 00117 MEM_POOL* pool = Mem_Pool(); 00118 Set_upper_linex((LINEX*)CXX_NEW(LINEX(pool),pool)); 00119 Get_upper_linex()->Set_term(LTKIND_CONST, upper, CONST_DESC,0); 00120 Set_lower_linex((LINEX*)CXX_NEW(LINEX(pool),pool)); 00121 Get_lower_linex()->Set_term(LTKIND_CONST, lower, CONST_DESC,0); 00122 Set_step_linex((LINEX*)CXX_NEW(LINEX(pool),pool)); 00123 Get_step_linex()->Set_term(LTKIND_CONST, step, CONST_DESC,0); 00124 if (segment_length <= 0) { 00125 Set_segment_length_linex(NULL); 00126 Set_segment_stride_linex(NULL); 00127 } else { 00128 Set_segment_length_linex((LINEX*)CXX_NEW(LINEX(pool),pool)); 00129 Get_segment_length_linex()->Set_term(LTKIND_CONST, segment_length, 00130 CONST_DESC,0); 00131 Set_segment_stride_linex((LINEX*)CXX_NEW(LINEX(pool),pool)); 00132 Get_segment_stride_linex()->Set_term(LTKIND_CONST, segment_stride, 00133 CONST_DESC,0); 00134 } 00135 Set_flags(0); 00136 } 00137 00138 //===================================================== 00139 // Set linexes for a constant two-strided array section 00140 //===================================================== 00141 void 00142 PROJECTED_NODE::Set_constant_two_strided_section(INT32 lower, 00143 INT32 upper, 00144 INT32 step, 00145 INT32 seg_len, 00146 INT32 seg_stride) 00147 { 00148 MEM_POOL* pool = Mem_Pool(); 00149 Set_lower_linex(CXX_NEW(LINEX(pool), pool)); 00150 Get_lower_linex()->Set_term(LTKIND_CONST, lower, CONST_DESC, 0); 00151 00152 Set_upper_linex(CXX_NEW(LINEX(pool), pool)); 00153 Get_upper_linex()->Set_term(LTKIND_CONST, upper, CONST_DESC, 0); 00154 00155 Set_step_linex(CXX_NEW(LINEX(pool), pool)); 00156 Get_step_linex()->Set_term(LTKIND_CONST, step, CONST_DESC, 0); 00157 00158 Set_segment_length_linex(CXX_NEW(LINEX(pool), pool)); 00159 Get_segment_length_linex()->Set_term(LTKIND_CONST, seg_len, CONST_DESC, 0); 00160 00161 Set_segment_stride_linex(CXX_NEW(LINEX(pool), pool)); 00162 Get_segment_stride_linex()->Set_term(LTKIND_CONST, seg_stride, CONST_DESC,0); 00163 00164 Set_flags(0); 00165 } 00166 00167 //----------------------------------------------------------------------- 00168 // NAME: PROJECTED_NODE::Fill_Out 00169 // FUNCTION: Converts a projected node of the form [lb:NULL:NULL] to 00170 // [lb:lb:1]. 00171 //----------------------------------------------------------------------- 00172 00173 void PROJECTED_NODE::Fill_Out() 00174 { 00175 LINEX* lx_lower = Get_lower_linex(); 00176 LINEX* lx_upper = Get_upper_linex(); 00177 LINEX* lx_step = Get_step_linex(); 00178 if (lx_upper != NULL && lx_upper->Num_terms() >= 0 00179 && lx_step != NULL && lx_step->Num_terms() >= 0) 00180 return; 00181 Reset_is_unprojected(); 00182 if (lx_upper != NULL) 00183 lx_upper->Free_terms(); 00184 if (lx_step != NULL) 00185 lx_step->Free_terms(); 00186 lx_step->Set_term(LTKIND_CONST, (INT32) 1, CONST_DESC, 0); 00187 for (INT i = 0; i <= lx_lower->Num_terms(); i++) 00188 lx_upper->Set_term(lx_lower->Get_term(i)); 00189 } 00190 00191 //===================================== 00192 // Set the linexs in the projected node 00193 //===================================== 00194 void 00195 PROJECTED_NODE::Set_linexs(LINEX* low_new, 00196 LINEX* up_new, 00197 LINEX* step_new, 00198 LINEX* segment_length_new, 00199 LINEX* segment_stride_new) 00200 { 00201 Reset_node(); 00202 00203 if (low_new) 00204 low_new->Copy(Get_lower_linex()); 00205 if (up_new) 00206 up_new->Copy(Get_upper_linex()); 00207 if (step_new) 00208 step_new->Copy(Get_step_linex()); 00209 if (segment_length_new) 00210 00211 segment_length_new->Copy(Get_segment_length_linex()); 00212 if (segment_stride_new) 00213 segment_stride_new->Copy(Get_segment_stride_linex()); 00214 } 00215 00216 //================================================ 00217 // copy the terms from one linex to another 00218 // discard empty terms that may show up during 00219 // Set_to_kernel_image merge or subtract operation 00220 //================================================ 00221 void 00222 LINEX::Copy(LINEX *to) 00223 { 00224 if (this == to) 00225 return; 00226 00227 for (INT i = 0; i <= Num_terms(); ++i) { 00228 if ((Get_term(i)->Get_coeff() == 0 && 00229 Get_term(i)->Get_type() == LTKIND_CONST) || 00230 (Get_term(i)->Get_coeff() != 0)) 00231 to->Set_term(Get_term(i)); 00232 } 00233 } 00234 00235 //======================== 00236 // copy the projected node 00237 //======================== 00238 void 00239 PROJECTED_NODE::Copy(PROJECTED_NODE* to) 00240 { 00241 MEM_POOL* m = Mem_Pool(); 00242 if (this == to) 00243 return; 00244 00245 to->Set_flags(Get_flags()); 00246 00247 to->Set_lower_linex(CXX_NEW(LINEX(m), m)); 00248 Get_lower_linex()->Copy(to->Get_lower_linex()); 00249 00250 to->Set_upper_linex(CXX_NEW(LINEX(m), m)); 00251 Get_upper_linex()->Copy(to->Get_upper_linex()); 00252 00253 to->Set_step_linex(CXX_NEW(LINEX(m), m)); 00254 Get_step_linex()->Copy(to->Get_step_linex()); 00255 00256 if (Get_segment_length_linex() != NULL) { 00257 to->Set_segment_length_linex(CXX_NEW(LINEX(m), m)); 00258 Get_segment_length_linex()->Copy(to->Get_segment_length_linex()); 00259 } else { 00260 to->Set_segment_length_linex(NULL); 00261 } 00262 00263 if (Get_segment_stride_linex() != NULL) { 00264 to->Set_segment_stride_linex(CXX_NEW(LINEX(m), m)); 00265 Get_segment_stride_linex()->Copy(to->Get_segment_stride_linex()); 00266 } else { 00267 to->Set_segment_stride_linex(NULL); 00268 } 00269 } 00270 00271 //====================================== 00272 // construct and copy the projected node 00273 //====================================== 00274 void 00275 PROJECTED_REGION::Copy_projected_node(PROJECTED_NODE* node) 00276 { 00277 PROJECTED_NODE* to = Get_projected_node(Get_projected_array()->Newidx()); 00278 node->Copy(to); 00279 } 00280 00281 //=================================================================== 00282 // projected region constructor 00283 //=================================================================== 00284 PROJECTED_REGION::PROJECTED_REGION(PROJECTED_REGION* p) 00285 { 00286 Set_Mem_Pool(Mem_Pool()); 00287 Set_num_dims(p->Get_num_dims()); 00288 Set_type(p->Get_type()); 00289 Set_depth(p->Get_depth()); 00290 Set_projected_kernel(p->Get_projected_kernel()); 00291 Set_projected_array(CXX_NEW(PROJECTED_ARRAY(Mem_Pool()), Mem_Pool())); 00292 for (INT i = 0; i < Get_num_dims(); ++i) { 00293 Copy_projected_node(p->Get_projected_node(i)); 00294 } 00295 } 00296 00297 //=============================================== 00298 // check if the LINEX represents a constant value 00299 //=============================================== 00300 BOOL LINEX::Is_const() 00301 { 00302 return ((Num_terms() == 0) && (Get_term(0)->Get_type() == LTKIND_CONST)); 00303 } 00304 00305 //=================================================================== 00306 // return the max value assuming both the linexs have constant terms 00307 //=================================================================== 00308 INT 00309 LINEX::Max(LINEX* l) 00310 { 00311 Is_True(Is_const(), ("LINEX::Max - Expecting constant LINEX")); 00312 Is_True(l->Is_const(), ("LINEX::Max - Expecting constant LINEX")); 00313 00314 INT32 val1 = Get_term(0)->Get_coeff(); 00315 INT32 val2 = l->Get_term(0)->Get_coeff(); 00316 00317 return MAX(val1, val2); 00318 } 00319 00320 //============================================================================= 00321 // 2 linex structures are equivalent if their terms are the same 00322 //============================================================================= 00323 BOOL 00324 LINEX::Equivalent(LINEX &b ) 00325 { 00326 INT32 num_terms = Num_terms(); 00327 if (num_terms != b.Num_terms()) { 00328 return FALSE; 00329 } 00330 00331 for (INT i = 0; i <= num_terms; ++i) { 00332 if (!Get_term(i)->Equivalent(*b.Get_term(i))) { 00333 return FALSE; 00334 } 00335 } 00336 00337 return TRUE; 00338 } 00339 00340 //===================================================================== 00341 // 2 term structures are equivalent if their coeff, types etc are the 00342 // the same 00343 //===================================================================== 00344 BOOL 00345 TERM::Equivalent (TERM& t) 00346 { 00347 return (Get_type() == t.Get_type() && 00348 Get_coeff() == t.Get_coeff() && 00349 Get_desc() == t.Get_desc()); 00350 } 00351 00352 //================================================================= 00353 // set the terms of the linex 00354 //================================================================= 00355 void 00356 LINEX::Set_linex_terms(INT start_index, INT end_index, TERM* term) 00357 { 00358 for (INT i = start_index; i < end_index; ++i) { 00359 Set_term(&term[i]); 00360 } 00361 } 00362 00363 //==================================================================== 00364 // this function is used to create the linex structure from the 00365 // information in the summary. 00366 // MEM_POOL *pool : mem pool 00367 // TERM* term : the term array from the summary 00368 //==================================================================== 00369 void 00370 PROJECTED_NODE::Create_linex(TERM* term) 00371 { 00372 MEM_POOL* pool = Mem_Pool(); 00373 INT uterm_index = Get_ub_term_index(); 00374 INT lterm_index = Get_lb_term_index(); 00375 INT sterm_index = Get_step_term_index(); 00376 INT segment_length_index = Get_segment_length_term_index(); 00377 INT segment_stride_index = Get_segment_stride_term_index(); 00378 00379 INT uterm_count = Get_ub_term_count(); 00380 INT lterm_count = Get_lb_term_count(); 00381 INT sterm_count = Get_step_term_count(); 00382 INT segment_length_count = Get_segment_length_term_count(); 00383 INT segment_stride_count = Get_segment_stride_term_count(); 00384 00385 // Let the constructor do the initializiation 00386 Set_upper_linex((LINEX*) CXX_NEW(LINEX(pool), pool)); 00387 Set_lower_linex((LINEX*) CXX_NEW(LINEX(pool), pool)); 00388 Set_step_linex((LINEX*) CXX_NEW(LINEX(pool), pool)); 00389 if (segment_length_count > 0) 00390 Set_segment_length_linex((LINEX*) CXX_NEW(LINEX(pool), pool)); 00391 else 00392 Set_segment_length_linex(NULL); 00393 if (segment_stride_count > 0) 00394 Set_segment_stride_linex((LINEX*) CXX_NEW(LINEX(pool), pool)); 00395 else 00396 Set_segment_stride_linex(NULL); 00397 00398 Get_upper_linex()->Set_linex_terms(uterm_index, uterm_index+uterm_count, 00399 term); 00400 Get_lower_linex()->Set_linex_terms(lterm_index, lterm_index+lterm_count, 00401 term); 00402 Get_step_linex()->Set_linex_terms(sterm_index, sterm_index+sterm_count, 00403 term); 00404 if (segment_length_count > 0) 00405 Get_segment_length_linex()->Set_linex_terms(segment_length_index, 00406 segment_length_index+segment_length_count, term); 00407 if (segment_stride_count > 0) 00408 Get_segment_stride_linex()->Set_linex_terms(segment_stride_index, 00409 segment_stride_index+segment_stride_count, term); 00410 } 00411 00412 //==================================================================== 00413 // this function is used to create the linex structure from the 00414 // information in the summary. 00415 // MEM_POOL *pool : memory pool 00416 // TERM *term : the term array from the summary 00417 //==================================================================== 00418 void 00419 LOOPINFO::Create_linex(TERM* term) 00420 { 00421 MEM_POOL* pool = Mem_Pool(); 00422 00423 // NOTE: because indices and counts are unioned with LINEX pointers, 00424 // their values must be fetched before pointers are assigned 00425 INT ub_start = Get_ub_term_index(); 00426 INT ub_end = ub_start + Get_ub_term_count(); 00427 INT lb_start = Get_lb_term_index(); 00428 INT lb_end = lb_start + Get_lb_term_count(); 00429 INT step_start = Get_step_term_index(); 00430 INT step_end = step_start + Get_step_term_count(); 00431 00432 if (!Is_messy_ub()) { 00433 u1.u3._upper_linex = CXX_NEW(LINEX(pool), pool); 00434 u1.u3._upper_linex->Set_linex_terms(ub_start, ub_end, term); 00435 } 00436 00437 if (!Is_messy_lb()) { 00438 u1.u3._lower_linex = CXX_NEW(LINEX(pool), pool); 00439 u1.u3._lower_linex->Set_linex_terms(lb_start, lb_end, term); 00440 } 00441 00442 if (!Is_messy_step()) { 00443 u1.u3._step_linex = CXX_NEW(LINEX(pool), pool); 00444 u1.u3._step_linex->Set_linex_terms(step_start, step_end, term); 00445 } 00446 } 00447 00448 //================================================================== 00449 // initialize the linex dynamic array structure 00450 //================================================================== 00451 void 00452 LINEX::Init(MEM_POOL *m) 00453 { 00454 // call placement new to initialize linex 00455 new (this) LINEX(m); 00456 } 00457 00458 //=================================================================== 00459 // Find the position of this symbol in the symbol list 00460 // if found return the position else add this symbol to the list 00461 // and add a variable to the system of equations 00462 //=================================================================== 00463 extern INT 00464 Locate_symbol(LOOP_SYMBOL_ARRAY* syms, 00465 SYSTEM_OF_EQUATIONS* soe, 00466 const LOOP_SYMBOL& symbol) 00467 { 00468 INT i; 00469 00470 for (i = 0; i < syms->Elements(); ++i) { 00471 if ((*syms)[i] == symbol) { 00472 return i; 00473 } 00474 } 00475 00476 syms->AddElement(symbol); 00477 soe->Add_Vars(1); 00478 00479 return i; 00480 } 00481 00482 //======================================================================== 00483 // Add a linex to the system of equations 00484 // The system of equations is setup as: 00485 // A*X + B*Y + C*Z <= b 00486 // X is a vector representing dimensions of the region 00487 // Y is a vector representing the loop indices 00488 // Z is a list of the symbolic variables in the linear term 00489 // b is a vector of constant offsets 00490 //======================================================================== 00491 void 00492 LINEX::Add_access(SYSTEM_OF_EQUATIONS *soe, 00493 mUINT8 depth, 00494 INT num_dim, 00495 INT axle, 00496 INT num_syms, 00497 ACTION_TYPE act, 00498 LOOP_SYMBOL_ARRAY* sym, 00499 BOOL trace) 00500 { 00501 INT pos, c = 0; 00502 BOOL ltkind_subscr = FALSE; 00503 00504 if (trace) { 00505 fprintf(stderr, "\n Add_access: Adding a LINEX to the SOE\n"); 00506 Print(stderr); 00507 fprintf(stderr, "\n to SOE:\n"); 00508 soe->Print(stderr); 00509 } 00510 00511 // the size of the vector is = # of dimensions (for coupled 00512 // subscript values) + # of symbolic constants + # of loop indices + 1 00513 INT vector_size = num_dim + depth + num_syms + 1; 00514 if (trace) { 00515 printf("num_dim = %d, depth = %d, num_syms = %d vector size %d \n", 00516 num_dim, depth, num_syms,vector_size); 00517 } 00518 00519 mINT32* v = (mINT32*) alloca(sizeof(mINT32) * vector_size); 00520 bzero(v, sizeof(mINT32) * vector_size); 00521 00522 // for each term store the coeff in the right place in the vector 00523 for (INT i = 0; i <= Num_terms(); ++i) { 00524 TERM* term = Get_term(i); 00525 switch (term->Get_type()) { 00526 00527 case LTKIND_CONST: 00528 c = term->Get_coeff(); 00529 break; 00530 00531 case LTKIND_LINDEX: 00532 // set the value of matrix A 00533 // note, when we first start out this is all zeros 00534 // we are setting this term to one in the case of the equality 00535 // constraint implying that this particular dimension or axle is 00536 // equal to the subscript expression 00537 v[num_dim+term->Get_desc()] = term->Get_coeff(); 00538 break; 00539 00540 case LTKIND_SUBSCR: 00541 v[term->Get_desc()] = term->Get_coeff(); 00542 ltkind_subscr = TRUE; 00543 break; 00544 00545 case LTKIND_IV: 00546 pos = Locate_symbol(sym, soe, LOOP_SYMBOL(term->Get_desc())); 00547 v[num_dim + depth + pos] = term->Get_coeff(); 00548 break; 00549 00550 case LTKIND_NONE: 00551 Fail_FmtAssertion("Add_access: invalid ltkind = LTKIND_NONE"); 00552 break; 00553 } 00554 } 00555 00556 if (!ltkind_subscr) { 00557 if (act == ACTION_LO) 00558 v[axle] = -1; 00559 else 00560 v[axle] = 1; 00561 } 00562 00563 // if the action is equal implying this is an 00564 // equality constraint or an upper bound constraint 00565 // and hence we reverse coefficients since 00566 // once they move to the other side of the equation they 00567 // will change signs 00568 if (act != ACTION_LO) { 00569 for (INT i = num_dim; i < vector_size; ++i) 00570 v[i] = -v[i]; 00571 } 00572 00573 // throw in the constant offset on the rhs 00574 if (act == ACTION_LO) 00575 c = -c; 00576 00577 // note, we need to add in the equality constraints for 00578 // the subscript expressions 00579 if (act != ACTION_EQ) 00580 soe->Add_Le(v, c); 00581 else 00582 // for equality constraints add to the set of soes 00583 // containing equalities 00584 soe->Add_Eq(v,c); 00585 00586 if (trace) { 00587 fprintf(stderr,"\n Add_access: New SOE is:\n"); 00588 soe->Print(stderr); 00589 } 00590 } 00591 00592 //========================================================================== 00593 // Add the axle 'pos' of REGION 'a' to the SOE 'soe'. 00594 // Convert one equation into two inequalities if convert_equation is TRUE 00595 //========================================================================== 00596 extern void 00597 Add_to_SOE(PROJECTED_REGION* a, 00598 const INT pos, 00599 SYSTEM_OF_EQUATIONS* soe, 00600 const BOOL convert_equation, 00601 LOOP_SYMBOL_ARRAY* sym, 00602 INT depth, 00603 BOOL trace) 00604 { 00605 #ifdef IPA_SUMMARY 00606 INT num_syms = Ivar->Elements(); 00607 #else 00608 INT num_syms = IPA_Ivar_Count; 00609 #endif 00610 00611 PROJECTED_ARRAY* array = a->Get_projected_array(); 00612 PROJECTED_NODE* node = &(*array)[pos]; 00613 00614 if (!node->Is_unprojected() && 00615 node->Get_upper_linex()->Num_terms() != -1) { 00616 node->Get_lower_linex()->Add_access(soe, depth, a->Get_num_dims(), pos, 00617 num_syms, ACTION_LO, 00618 sym, trace); 00619 00620 node->Get_upper_linex()->Add_access(soe, depth, a->Get_num_dims(), pos, 00621 num_syms, ACTION_UP, 00622 sym, trace); 00623 } 00624 else { 00625 if (convert_equation) { 00626 node->Get_lower_linex()->Add_access(soe, depth, a->Get_num_dims(), pos, 00627 num_syms, ACTION_LO, 00628 sym, trace); 00629 00630 node->Get_lower_linex()->Add_access(soe, depth, a->Get_num_dims(), pos, 00631 num_syms, ACTION_UP, 00632 sym, trace); 00633 } 00634 else { 00635 node->Get_lower_linex()->Add_access(soe, depth, a->Get_num_dims(), pos, 00636 num_syms, ACTION_EQ, 00637 sym, trace); 00638 } 00639 } 00640 } 00641 00642 //=================================================================== 00643 // projected region constructor 00644 //=================================================================== 00645 PROJECTED_REGION::PROJECTED_REGION(mINT16 type, 00646 mUINT8 depth, 00647 mUINT8 dim, 00648 MEM_POOL* mem_pool) 00649 : _type (type), 00650 _num_dims (dim), 00651 _depth (depth), 00652 _mem_pool (mem_pool) 00653 { 00654 u2._projected_kernel = 0; 00655 u1._region = CXX_NEW(PROJECTED_ARRAY(mem_pool), mem_pool); 00656 u1._region->Force_Alloc_array(dim); 00657 u1._region->Setidx(dim-1); 00658 for (INT i = 0; i < dim; i++) { 00659 (*(u1._region))[i].Init(mem_pool); 00660 } 00661 } 00662 00663 //=================================================================== 00664 // Initialize a projected node 00665 //=================================================================== 00666 void 00667 PROJECTED_NODE::Init(MEM_POOL *m) 00668 { 00669 Set_Mem_Pool(m); 00670 00671 Set_upper_linex(CXX_NEW(LINEX(m), m)); 00672 Get_upper_linex()->Init(m); 00673 00674 Set_lower_linex(CXX_NEW(LINEX(m), m)); 00675 Get_lower_linex()->Init(m); 00676 00677 Set_step_linex(CXX_NEW(LINEX(m), m)); 00678 Get_step_linex()->Init(m); 00679 00680 Set_segment_length_linex(NULL); 00681 Set_segment_stride_linex(NULL); 00682 00683 Set_flags(0); 00684 } 00685 00686 //============================================================================= 00687 // Two nodes are equal if their upper, lower and step linex 00688 // structures are equivalent 00689 //============================================================================= 00690 BOOL 00691 PROJECTED_NODE::Equivalent(PROJECTED_NODE &b) 00692 { 00693 return ((Get_flags() == b.Get_flags()) && 00694 (Get_upper_linex()->Equivalent(*b.Get_upper_linex())) && 00695 (Get_lower_linex()->Equivalent(*b.Get_lower_linex())) && 00696 (Get_step_linex()->Equivalent(*b.Get_step_linex())) && 00697 (Get_segment_length_linex() == NULL && 00698 b.Get_segment_length_linex() == NULL || 00699 Get_segment_length_linex() != NULL && 00700 b.Get_segment_length_linex() == NULL && 00701 Get_segment_length_linex()-> 00702 Equivalent(*b.Get_segment_length_linex())) && 00703 (Get_segment_stride_linex() == NULL && 00704 b.Get_segment_stride_linex() == NULL || 00705 Get_segment_stride_linex() != NULL && 00706 b.Get_segment_stride_linex() == NULL && 00707 Get_segment_stride_linex()-> 00708 Equivalent(*b.Get_segment_stride_linex()))); 00709 } 00710 00711 //========================================================================== 00712 // PROJECTED_REGION::Equivalent 00713 // return TRUE if 2 projected regions have the same section 00714 //========================================================================== 00715 BOOL 00716 PROJECTED_REGION::Equivalent(PROJECTED_REGION* p) 00717 { 00718 if (Is_messy_region() && p->Is_messy_region()) { 00719 return TRUE; 00720 } 00721 00722 INT num_dims = Get_num_dims(); 00723 if (num_dims != p->Get_num_dims()) { 00724 return FALSE; 00725 } 00726 00727 // WARNING: 00728 // This function is currently called only from Same_Shape 00729 // to compare shapes of two declaration regions. Becuase of 00730 // that, it can ignore the highest order dimension, but if 00731 // the function is to be used for general comparison of 00732 // PROJECTED_REGIONs, it would have to be changed! 00733 00734 for (INT i = 1; i < num_dims; ++i) { 00735 PROJECTED_NODE* p1 = Get_projected_node(i); 00736 PROJECTED_NODE* p2 = p->Get_projected_node(i); 00737 Is_True(p1 && p2, ("PROJECTED_REGION::Equivalent: NULL projected node\n")); 00738 if (!p1->Equivalent(*p2)) { 00739 return FALSE; 00740 } 00741 } 00742 00743 return TRUE; 00744 } 00745 00746 //========================================================================== 00747 // PROJECTED_REGION::May_Union 00748 // MERGE SECTIONS 00749 // ALGORITHM: walk the control dependence graph 00750 // For each reference, check if it is in a loop, control flow node or 00751 // not projected. For each of them check if the section is projected, 00752 // bottom (i.e. non-constant symbolic terms, or complex terms). 00753 // PS. make sure that there is no memory leak in here 00754 //========================================================================== 00755 BOOL 00756 PROJECTED_REGION::May_Union(PROJECTED_REGION& b, 00757 BOOL trace) 00758 { 00759 if (trace) { 00760 fprintf(stderr,"Union two PROJECTED REGIONs \n"); 00761 b.Print(stderr); 00762 Print(stderr); 00763 } 00764 00765 // First, the simple tests. 00766 if (Is_messy_region()) { 00767 return FALSE; 00768 } 00769 else if (b.Is_messy_region()) { 00770 Set_messy_region(); 00771 return TRUE; 00772 } 00773 00774 BOOL change = FALSE; 00775 MEM_POOL* local_pool = Mem_Pool(); 00776 LOOPINFO l(local_pool); 00777 00778 for (INT i = 0; i < Get_num_dims(); ++i) { 00779 00780 // skip the dimension that's already messy 00781 PROJECTED_NODE* ax = Get_projected_node(i); 00782 if (ax->Has_all_messy_bounds()) { 00783 continue; 00784 } 00785 00786 // check if the merged dimension is messy 00787 PROJECTED_NODE* bx = b.Get_projected_node(i); 00788 if (ax->Is_messy_lb() || ax->Is_messy_ub() || 00789 bx->Is_messy_lb() || bx->Is_messy_ub()) { 00790 ax->Set_all_messy_bounds(); 00791 change = TRUE; 00792 continue; 00793 } 00794 00795 ax->Fill_Out(); 00796 bx->Fill_Out(); 00797 00798 // Handle mismatched steps using GCD rule. 00799 LINEX* lx_a_step = ax->Get_step_linex(); 00800 LINEX* lx_b_step = bx->Get_step_linex(); 00801 if (!lx_a_step->Is_const() || !lx_b_step->Is_const()) { 00802 if (!lx_a_step->Is_const() || lx_a_step->Get_constant_term() != 1) { 00803 lx_a_step->Free_terms(); 00804 lx_a_step->Set_term(LTKIND_CONST, (mINT32) 1, CONST_DESC, 0); 00805 change = TRUE; 00806 } 00807 } 00808 else { 00809 INT a_coeff = lx_a_step->Get_term(0)->Get_coeff(); 00810 INT b_coeff = lx_b_step->Get_term(0)->Get_coeff(); 00811 INT gcd = Gcd(a_coeff, b_coeff); 00812 LINEX* ax_lower = ax->Get_lower_linex(); 00813 LINEX* bx_lower = bx->Get_lower_linex(); 00814 LINEX* lx_diff = ax_lower->Subtract(bx_lower); 00815 lx_diff->Simplify(); 00816 if (!lx_diff->Is_const()) { 00817 if (lx_a_step->Get_term(0)->Get_coeff() != 1) { 00818 lx_a_step->Get_term(0)->Set_coeff(1); 00819 change = TRUE; 00820 } 00821 } 00822 else { 00823 INT diff = lx_diff->Get_term(0)->Get_coeff(); 00824 if (diff < 0) 00825 diff = -diff; 00826 if (diff % gcd != 0) { 00827 if (lx_a_step->Get_term(0)->Get_coeff() != 1) { 00828 lx_a_step->Get_term(0)->Set_coeff(1); 00829 change = TRUE; 00830 } 00831 } 00832 else { 00833 if (lx_a_step->Get_term(0)->Get_coeff() != gcd) { 00834 lx_a_step->Get_term(0)->Set_coeff(gcd); 00835 change = TRUE; 00836 } 00837 } 00838 } 00839 } 00840 00841 // Now, try to merge them 00842 SYSTEM_OF_EQUATIONS* soe = 00843 CXX_NEW(SYSTEM_OF_EQUATIONS(0, 0, b.Get_num_dims() + b.Get_depth(), 00844 local_pool), local_pool); 00845 LOOP_SYMBOL_ARRAY* syms = 00846 CXX_NEW(LOOP_SYMBOL_ARRAY(local_pool), local_pool); 00847 00848 // Build the system of inequalities for axle 'i' 00849 Add_to_SOE(this, i, soe, TRUE, syms, Get_depth(), trace); 00850 Add_to_SOE(&b, i, soe, TRUE, syms, Get_depth(), trace); 00851 00852 // Get rid of the redundant constraints to find the 00853 // intersection. 00854 if (soe->Copy_To_Work()) { 00855 BOOL* is_redundant = 00856 CXX_NEW_ARRAY(BOOL, soe->Num_Le_Constraints(), local_pool); 00857 INT num_con = soe->Num_Le_Constraints(); 00858 // The following is the first part of SOE::Elim_Simple_Redundant() 00859 num_con -= soe->Mark_Simple_Redundant(is_redundant); 00860 if (num_con > 2) { 00861 // SOE::Mark_New_Redundant() skips the inequalities that 00862 // are already marked as redundant in the parameter. 00863 num_con -= soe->Mark_New_Redundant(is_redundant); 00864 } 00865 // If we have only two constraints left, the redundant pairs 00866 // constitute the union. 00867 if (num_con == 2) { 00868 if (!((is_redundant[0] && !is_redundant[2] 00869 || !is_redundant[0] && is_redundant[2]) 00870 && (is_redundant[1] && !is_redundant[3] 00871 || !is_redundant[1] && is_redundant[3]))) { 00872 ax->Set_all_messy_bounds(); 00873 change = TRUE; 00874 continue; 00875 } 00876 if (!ax->Matching_Segment_Stride(bx) 00877 || ax->Get_segment_length_linex() != NULL 00878 && !ax->Get_segment_length_linex()->Is_const() 00879 || bx->Get_segment_length_linex() != NULL 00880 && !bx->Get_segment_length_linex()->Is_const()) { 00881 LINEX* lx_seg_length = ax->Get_segment_length_linex(); 00882 lx_seg_length->Free_terms(); 00883 LINEX* lx_seg_stride = ax->Get_segment_stride_linex(); 00884 lx_seg_stride->Free_terms(); 00885 } 00886 else if (ax->Get_segment_stride_linex() != NULL) { 00887 LINEX* lx_a_seg_length = ax->Get_segment_length_linex(); 00888 INT a_const_value = lx_a_seg_length->Get_constant_term(); 00889 LINEX* lx_b_seg_length = bx->Get_segment_length_linex(); 00890 INT b_const_value = lx_b_seg_length->Get_constant_term(); 00891 INT difference = a_const_value > b_const_value 00892 ? a_const_value - b_const_value : b_const_value - a_const_value; 00893 ax->Get_segment_length_linex()->Set_term(LTKIND_CONST, 00894 difference, CONST_DESC, 0); 00895 ax->Get_segment_length_linex()->Simplify(); 00896 LINEX* ax_lower = ax->Get_lower_linex(); 00897 LINEX* bx_lower = bx->Get_lower_linex(); 00898 LINEX* lx_diff = ax_lower->Subtract(bx_lower); 00899 if (!lx_diff->Is_const()) { 00900 ax->Get_segment_length_linex()->Free_terms(); 00901 ax->Set_segment_length_linex(NULL); 00902 ax->Get_segment_stride_linex()->Free_terms(); 00903 ax->Set_segment_stride_linex(NULL); 00904 } 00905 else { 00906 INT difference = lx_diff->Get_constant_term(); 00907 if (difference < 0) 00908 difference = -difference; 00909 ax->Get_segment_length_linex()->Set_term(LTKIND_CONST, 00910 difference, CONST_DESC,0); 00911 ax->Get_segment_length_linex()->Simplify(); 00912 } 00913 } 00914 00915 // The redundant equations are the ones we want to retain 00916 LINEX* lb = ax->Get_lower_linex(); 00917 if (lb && !lb->Equivalent(*(bx->Get_lower_linex()))) { 00918 if (!is_redundant[0]) { 00919 lb->Free_terms(); 00920 (bx->Get_lower_linex())->Copy(lb); 00921 change = TRUE; 00922 } 00923 } 00924 00925 LINEX* ub = ax->Get_upper_linex(); 00926 if (ub && !ub->Equivalent(*(bx->Get_upper_linex()))) { 00927 if (!is_redundant[1]) { 00928 ub->Free_terms(); 00929 (bx->Get_upper_linex())->Copy(ub); 00930 change = TRUE; 00931 } 00932 } 00933 00934 } 00935 else { 00936 // num constraints is not equal to NULL 00937 ax->Set_all_messy_bounds(); 00938 change = TRUE; 00939 } 00940 } 00941 else { 00942 // if not soe->Copy_To_Work 00943 ax->Set_all_messy_bounds(); 00944 change = TRUE; 00945 } 00946 } 00947 00948 if (trace) { 00949 fprintf(stderr,"Result of Unioning two PROJECTED REGIONs \n"); 00950 Print(stderr); 00951 } 00952 00953 return change; 00954 } 00955 00956 //===================================================================== 00957 // check if all the terms are the same 00958 //===================================================================== 00959 BOOL 00960 TERM::Is_equal(TERM* t, INT count) 00961 { 00962 for (INT i = 0; i <= count; ++i) { 00963 if (! t[i].Equivalent(this[i])) { 00964 return FALSE; 00965 } 00966 } 00967 return TRUE; 00968 } 00969 00970 //=================================================================== 00971 // Copy all the relevant fields when writing out the projected region 00972 //=================================================================== 00973 void 00974 PROJECTED_REGION::Copy_write(PROJECTED_REGION *p_in) 00975 { 00976 Set_type(p_in->Get_type()); 00977 Set_num_dims(p_in->Get_num_dims()); 00978 Set_depth(p_in->Get_depth()); 00979 if (p_in->Is_passed()) 00980 { 00981 Set_callsite_id(p_in->Get_callsite_id()); 00982 Set_actual_id(p_in->Get_actual_id()); 00983 } 00984 } 00985 00986 void 00987 Print_Symbol_Array(LOOP_SYMBOL_ARRAY* sa, FILE *fp) 00988 { 00989 for (INT i = 0; i <= sa->Lastidx(); i++) { 00990 fprintf(fp, "[%d] ", i); 00991 (*sa)[i].Print(fp); 00992 } 00993 } 00994 00995 //===================================================================== 00996 // PROJECTED_REGION::Constant_bounds 00997 // check if dimensions first_dim..num_dims-1 have constant bounds 00998 //===================================================================== 00999 BOOL 01000 PROJECTED_REGION::Constant_bounds(mUINT8 first_dim) 01001 { 01002 for (INT i = first_dim; i < _num_dims; ++i) { 01003 PROJECTED_NODE *node = Get_projected_node(i); 01004 LINEX* lower = node->Get_upper_linex(); 01005 LINEX* upper = node->Get_upper_linex(); 01006 if (!lower || !lower->Is_const() || !upper || !upper->Is_const()) { 01007 return FALSE; 01008 } 01009 } 01010 return TRUE; 01011 } 01012 01013 //==================================================================== 01014 // return the value in the constant term 01015 //==================================================================== 01016 INT 01017 LINEX::Get_constant_term() 01018 { 01019 for (INT i = 0; i <= Num_terms(); ++i) { 01020 if (Get_term(i)->Get_type() == LTKIND_CONST) 01021 return Get_term(i)->Get_coeff(); 01022 } 01023 // if no constant term found 01024 return 0; 01025 } 01026 01027 //==================================================================== 01028 // return the projected region number (i) 01029 //==================================================================== 01030 PROJECTED_REGION* 01031 REGION_ARRAYS::Get_Projected_Region(INT i) 01032 { 01033 PROJECTED_REGION_INFO_ARRAY *info = Get_projected_region_array(); 01034 01035 Is_True(info && info->Lastidx() != -1, ("Expecting at least 1 projected region in Reshape \n")); 01036 Is_True(info->Lastidx() >= i, ("Projected_Region %d exceeded size of array %d \n", i, info->Lastidx())); 01037 01038 PROJECTED_REGION_INFO *region_info = &(*info)[i]; 01039 PROJECTED_REGION *proj_shape = region_info->Get_projected_region(); 01040 Is_True(proj_shape, ("NULL Projected Region in REGION_ARRAYS::Get_Projected_Region \n")); 01041 01042 return proj_shape; 01043 } 01044 01045 //----------------------------------------------------------------------- 01046 // NAME: LINEX::Remove_Zero_Terms 01047 // FUNCTION: Remove all terms with zero coefficients from the LINEX. 01048 //----------------------------------------------------------------------- 01049 01050 void LINEX::Remove_Zero_Terms() 01051 { 01052 INT j = 0; 01053 INT num_init_terms = Num_terms(); 01054 INT i; 01055 01056 for (i = 0; i <= Num_terms(); i++) { 01057 TERM* tm = Get_term(i); 01058 if (tm->Get_coeff() != 0) { 01059 if (i != j) 01060 _larray[j] = _larray[i]; 01061 j++; 01062 } 01063 } 01064 01065 INT difference = i - j; 01066 for (i = 0; i < difference; i++) 01067 _larray.Decidx(); 01068 01069 01070 // if there was a zero term then put 1 term back if all terms 01071 // have been eliminated 01072 if ((Num_terms() == -1) && (num_init_terms != -1)) 01073 { 01074 Set_term(LTKIND_CONST, 0, CONST_DESC, 0); 01075 } 01076 } 01077 01078 //----------------------------------------------------------------------- 01079 // NAME: LINEX::Simplify 01080 // FUNCTION: Simplify the LINEX by combining terms which match on all 01081 // components except possibly coefficients. 01082 //----------------------------------------------------------------------- 01083 01084 void LINEX::Simplify() 01085 { 01086 for (INT i = 0; i <= Num_terms(); i++) { 01087 TERM* tm_i = Get_term(i); 01088 for (INT j = i + 1; j <= Num_terms(); j++) { 01089 TERM* tm_j = Get_term(j); 01090 if (tm_i->Get_type() == tm_j->Get_type() 01091 && tm_i->Get_desc() == tm_j->Get_desc() 01092 && tm_i->Get_projected_level() == tm_j->Get_projected_level()) { 01093 tm_i->Set_coeff(tm_i->Get_coeff() + tm_j->Get_coeff()); 01094 tm_j->Set_coeff(0); 01095 } 01096 } 01097 } 01098 Remove_Zero_Terms(); 01099 } 01100 01101 //----------------------------------------------------------------------- 01102 // NAME: PROJECTED_NODE::Simplify 01103 // FUNCTION: Simplify the LINEXes in the PROJECTED_NODE. 01104 //----------------------------------------------------------------------- 01105 01106 void PROJECTED_NODE::Simplify() 01107 { 01108 if (!Is_messy_lb()) { 01109 LINEX* lx_lower = Get_lower_linex(); 01110 lx_lower->Simplify(); 01111 } 01112 if (!Is_messy_ub()) { 01113 LINEX* lx_upper = Get_upper_linex(); 01114 lx_upper->Simplify(); 01115 } 01116 if (!Is_messy_step()) { 01117 LINEX* lx_step = Get_step_linex(); 01118 lx_step->Simplify(); 01119 } 01120 if (Get_segment_length_linex() != NULL) 01121 Get_segment_length_linex()->Simplify(); 01122 if (Get_segment_stride_linex() != NULL) 01123 Get_segment_stride_linex()->Simplify(); 01124 } 01125 01126 //----------------------------------------------------------------------- 01127 // NAME: PROJECTED_REGION::LNO_Simplify 01128 // FUNCTION: Simplify the LINEXes in the PROJECTED_REGION. 01129 //----------------------------------------------------------------------- 01130 01131 void PROJECTED_REGION::Simplify() 01132 { 01133 if (Is_messy_region()) 01134 return; 01135 for (INT i = 0; i < Get_num_dims(); i++) { 01136 PROJECTED_NODE* pn = Get_projected_node(i); 01137 pn->Simplify(); 01138 } 01139 } 01140 01141 BOOL PROJECTED_REGION::Has_Messy_Bounds() 01142 { 01143 for (INT i = 0; i < Get_num_dims(); i++) { 01144 PROJECTED_NODE* pn = Get_projected_node(i); 01145 if (pn->Has_a_messy_bound()) 01146 return TRUE; 01147 } 01148 return FALSE; 01149 } 01150 01151 BOOL PROJECTED_REGION::Has_Important_Messy_Bounds() 01152 { 01153 for (INT i = 1; i < Get_num_dims(); i++) { 01154 PROJECTED_NODE* pn = Get_projected_node(i); 01155 if (pn->Has_a_messy_bound()) 01156 return TRUE; 01157 } 01158 return FALSE; 01159 } 01160 01161 void PROJECTED_REGION::Fill_Out() 01162 { 01163 if (Is_messy_region()) 01164 return; 01165 Reset_is_unprojected(); 01166 for (INT i = 0; i < Get_num_dims(); i++) { 01167 PROJECTED_NODE* pn = Get_projected_node(i); 01168 pn->Fill_Out(); 01169 } 01170 } 01171 01172 BOOL PROJECTED_NODE::Matching_Segment_Stride(PROJECTED_NODE* pn) 01173 { 01174 if (pn == NULL) 01175 return FALSE; 01176 01177 LINEX* ss_one = Get_segment_stride_linex(); 01178 LINEX* ss_two = pn->Get_segment_stride_linex(); 01179 01180 if (ss_one == NULL && ss_two == NULL) 01181 return TRUE; 01182 if (ss_one == NULL || ss_two == NULL) 01183 return FALSE; 01184 return ss_one->Equivalent(*ss_two); 01185 } 01186 01187 BOOL PROJECTED_REGION::Matching_Segment_Stride(PROJECTED_REGION* pr) 01188 { 01189 if (pr == NULL) 01190 return FALSE; 01191 if (Is_messy_region() || pr->Is_messy_region()) 01192 return (Is_messy_region() == pr->Is_messy_region()); 01193 if (Get_num_dims() != pr->Get_num_dims()) 01194 return FALSE; 01195 for (INT i = 0; i < Get_num_dims(); i++) { 01196 PROJECTED_NODE* pn_one = Get_projected_node(i); 01197 PROJECTED_NODE* pn_two = pr->Get_projected_node(i); 01198 if (!pn_one->Matching_Segment_Stride(pn_two)) 01199 return FALSE; 01200 } 01201 return TRUE; 01202 } 01203 01204 //----------------------------------------------------------------------- 01205 // NAME: LINEX::Merge 01206 // FUNCTION: Return l1 + this. 01207 //----------------------------------------------------------------------- 01208 01209 LINEX* LINEX::Merge(LINEX *l1) 01210 { 01211 INT c = 0; 01212 01213 // Set up the mem pool 01214 FmtAssert(_larray.Get_Mem_Pool() == l1->_larray.Get_Mem_Pool(), 01215 ("LINEX::Merge: Inconsistent mem pools")); 01216 MEM_POOL* mem_pool = _larray.Get_Mem_Pool(); 01217 01218 // Determine the size of the coefficient arrays 01219 INT coeff_max = -1; 01220 INT sub_coeff_max = -1; 01221 INT isym_coeff_max = -1; 01222 INT i; 01223 01224 for (i = 0; i <= Num_terms(); i++) { 01225 TERM* term = Get_term(i); 01226 switch (term->Get_type()) { 01227 case LTKIND_LINDEX: 01228 if (term->Get_desc() > coeff_max) 01229 coeff_max = term->Get_desc(); 01230 break; 01231 case LTKIND_SUBSCR: 01232 if (term->Get_desc() > sub_coeff_max) 01233 sub_coeff_max = term->Get_desc(); 01234 break; 01235 case LTKIND_IV: 01236 if (term->Get_desc() > isym_coeff_max) 01237 isym_coeff_max = term->Get_desc(); 01238 break; 01239 } 01240 } 01241 01242 for (i = 0; i <= l1->Num_terms(); i++) { 01243 TERM* term = l1->Get_term(i); 01244 switch (term->Get_type()) { 01245 case LTKIND_LINDEX: 01246 if (term->Get_desc() > coeff_max) 01247 coeff_max = term->Get_desc(); 01248 break; 01249 case LTKIND_SUBSCR: 01250 if (term->Get_desc() > sub_coeff_max) 01251 sub_coeff_max = term->Get_desc(); 01252 break; 01253 case LTKIND_IV: 01254 if (term->Get_desc() > isym_coeff_max) 01255 isym_coeff_max = term->Get_desc(); 01256 break; 01257 } 01258 } 01259 01260 // Allocate them. 01261 INT* coeff = (INT*) alloca(sizeof(INT) * (coeff_max + 1)); 01262 INT* sub_coeff = (INT*) alloca(sizeof(INT) * (sub_coeff_max + 1)); 01263 INT* isym_coeff = (INT*) alloca(sizeof(INT) * (isym_coeff_max + 1)); 01264 bzero(coeff, sizeof(INT) * (coeff_max + 1)); 01265 bzero(sub_coeff, sizeof(INT) * (sub_coeff_max + 1)); 01266 bzero(isym_coeff, sizeof(INT) * (isym_coeff_max + 1)); 01267 01268 LINEX* l = CXX_NEW(LINEX(mem_pool), mem_pool); 01269 01270 // For each term, store the coeff in the right place in the vector. 01271 for (i = 0; i <= Num_terms(); i++) { 01272 TERM *term = Get_term(i); 01273 switch (term->Get_type()) { 01274 case LTKIND_NONE: 01275 break; 01276 case LTKIND_CONST: 01277 c += term->Get_coeff(); 01278 break; 01279 case LTKIND_LINDEX: 01280 coeff[term->Get_desc()] += term->Get_coeff(); 01281 break; 01282 case LTKIND_SUBSCR: 01283 sub_coeff[term->Get_desc()] += term->Get_coeff(); 01284 break; 01285 case LTKIND_IV: 01286 isym_coeff[term->Get_desc()] += term->Get_coeff(); 01287 break; 01288 } 01289 } 01290 for (i = 0; i<= l1->Num_terms(); ++i) { 01291 TERM *term = l1->Get_term(i); 01292 switch (term->Get_type()) { 01293 case LTKIND_NONE: 01294 break; 01295 case LTKIND_CONST: 01296 c += term->Get_coeff(); 01297 break; 01298 case LTKIND_LINDEX: 01299 coeff[term->Get_desc()] += term->Get_coeff(); 01300 break; 01301 case LTKIND_SUBSCR: 01302 sub_coeff[term->Get_desc()] += term->Get_coeff(); 01303 break; 01304 case LTKIND_IV: 01305 isym_coeff[term->Get_desc()] += term->Get_coeff(); 01306 break; 01307 } 01308 } 01309 01310 // Put in the appropriate terms. 01311 l->Set_term(LTKIND_CONST, c, CONST_DESC, 0); 01312 for (i = 0; i <= coeff_max; i++) 01313 if (coeff[i]) 01314 l->Set_term(LTKIND_LINDEX, coeff[i], i, 0); 01315 for (i = 0; i <= sub_coeff_max; i++) 01316 if (sub_coeff[i]) 01317 l->Set_term(LTKIND_SUBSCR, sub_coeff[i], i, 0); 01318 for (i = 0; i <= isym_coeff_max; i++) 01319 if (isym_coeff[i]) 01320 l->Set_term(LTKIND_IV, isym_coeff[i], i, 0); 01321 01322 return l; 01323 } 01324 //----------------------------------------------------------------------- 01325 // NAME: LINEX::Subtract 01326 // FUNCTION: Return this - l1. 01327 //----------------------------------------------------------------------- 01328 01329 LINEX* LINEX::Subtract(LINEX *l1) 01330 { 01331 INT c = 0; 01332 01333 // Set up the mem pool 01334 FmtAssert(_larray.Get_Mem_Pool() == l1->_larray.Get_Mem_Pool(), 01335 ("LINEX::Subtract: Inconsistent mem pools")); 01336 MEM_POOL* mem_pool = _larray.Get_Mem_Pool(); 01337 01338 // Determine the size of the coefficient arrays 01339 INT coeff_max = -1; 01340 INT sub_coeff_max = -1; 01341 INT isym_coeff_max = -1; 01342 INT i; 01343 01344 for (i = 0; i <= Num_terms(); i++) { 01345 TERM* term = Get_term(i); 01346 switch (term->Get_type()) { 01347 case LTKIND_LINDEX: 01348 if (term->Get_desc() > coeff_max) 01349 coeff_max = term->Get_desc(); 01350 break; 01351 case LTKIND_SUBSCR: 01352 if (term->Get_desc() > sub_coeff_max) 01353 sub_coeff_max = term->Get_desc(); 01354 break; 01355 case LTKIND_IV: 01356 if (term->Get_desc() > isym_coeff_max) 01357 isym_coeff_max = term->Get_desc(); 01358 break; 01359 } 01360 } 01361 01362 for (i = 0; i <= l1->Num_terms(); i++) { 01363 TERM* term = l1->Get_term(i); 01364 switch (term->Get_type()) { 01365 case LTKIND_LINDEX: 01366 if (term->Get_desc() > coeff_max) 01367 coeff_max = term->Get_desc(); 01368 break; 01369 case LTKIND_SUBSCR: 01370 if (term->Get_desc() > sub_coeff_max) 01371 sub_coeff_max = term->Get_desc(); 01372 break; 01373 case LTKIND_IV: 01374 if (term->Get_desc() > isym_coeff_max) 01375 isym_coeff_max = term->Get_desc(); 01376 break; 01377 } 01378 } 01379 01380 // Allocate them. 01381 INT* coeff = (INT*) alloca(sizeof(INT) * (coeff_max + 1)); 01382 INT* sub_coeff = (INT*) alloca(sizeof(INT) * (sub_coeff_max + 1)); 01383 INT* isym_coeff = (INT*) alloca(sizeof(INT) * (isym_coeff_max + 1)); 01384 bzero(coeff, sizeof(INT) * (coeff_max + 1)); 01385 bzero(sub_coeff, sizeof(INT) * (sub_coeff_max + 1)); 01386 bzero(isym_coeff, sizeof(INT) * (isym_coeff_max + 1)); 01387 01388 LINEX* l = CXX_NEW(LINEX(mem_pool), mem_pool); 01389 01390 // For each term, store the coeff in the right place in the vector. 01391 for (i = 0; i <= Num_terms(); i++) { 01392 TERM *term = Get_term(i); 01393 switch (term->Get_type()) { 01394 case LTKIND_NONE: 01395 break; 01396 case LTKIND_CONST: 01397 c += term->Get_coeff(); 01398 break; 01399 case LTKIND_LINDEX: 01400 coeff[term->Get_desc()] += term->Get_coeff(); 01401 break; 01402 case LTKIND_SUBSCR: 01403 sub_coeff[term->Get_desc()] += term->Get_coeff(); 01404 break; 01405 case LTKIND_IV: 01406 isym_coeff[term->Get_desc()] += term->Get_coeff(); 01407 break; 01408 } 01409 } 01410 for (i = 0; i<= l1->Num_terms(); ++i) { 01411 TERM *term = l1->Get_term(i); 01412 switch (term->Get_type()) { 01413 case LTKIND_NONE: 01414 break; 01415 case LTKIND_CONST: 01416 c -= term->Get_coeff(); 01417 break; 01418 case LTKIND_LINDEX: 01419 coeff[term->Get_desc()] -= term->Get_coeff(); 01420 break; 01421 case LTKIND_SUBSCR: 01422 sub_coeff[term->Get_desc()] -= term->Get_coeff(); 01423 break; 01424 case LTKIND_IV: 01425 isym_coeff[term->Get_desc()] -= term->Get_coeff(); 01426 break; 01427 } 01428 } 01429 01430 // Put in the appropriate terms. 01431 l->Set_term(LTKIND_CONST, c, CONST_DESC, 0); 01432 for (i = 0; i <= coeff_max; i++) 01433 if (coeff[i]) 01434 l->Set_term(LTKIND_LINDEX, coeff[i], i, 0); 01435 for (i = 0; i <= sub_coeff_max; i++) 01436 if (sub_coeff[i]) 01437 l->Set_term(LTKIND_SUBSCR, sub_coeff[i], i, 0); 01438 for (i = 0; i <= isym_coeff_max; i++) 01439 if (isym_coeff[i]) 01440 l->Set_term(LTKIND_IV, isym_coeff[i], i, 0); 01441 01442 return l; 01443 } 01444