Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
ipa_section_main.cxx
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines