SundanceProductEvaluator.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
00030 
00031 #include "SundanceProductEvaluator.hpp"
00032 #include "SundanceEvalManager.hpp"
00033 #include "SundanceProductExpr.hpp"
00034 
00035 #include "PlayaTabs.hpp"
00036 #include "SundanceOut.hpp"
00037 
00038 using namespace Sundance;
00039 using namespace Sundance;
00040 using namespace Sundance;
00041 using namespace Teuchos;
00042 
00043 
00044 
00045 
00046 
00047 ProductEvaluator::ProductEvaluator(const ProductExpr* expr,
00048   const EvalContext& context)
00049   : BinaryEvaluator<ProductExpr>(expr, context),
00050     maxOrder_(this->sparsity()->maxOrder()),
00051     resultIndex_(maxOrder_+1),
00052     resultIsConstant_(maxOrder_+1),
00053     hasWorkspace_(maxOrder_+1),
00054     workspaceIsLeft_(maxOrder_+1),
00055     workspaceIndex_(maxOrder_+1),
00056     workspaceCoeffIndex_(maxOrder_+1),
00057     workspaceCoeffIsConstant_(maxOrder_+1),
00058     ccTerms_(maxOrder_+1),
00059     cvTerms_(maxOrder_+1),
00060     vcTerms_(maxOrder_+1),
00061     vvTerms_(maxOrder_+1),
00062     startingVectors_(maxOrder_+1),
00063     startingParities_(maxOrder_+1)
00064 {
00065   int verb = context.evalSetupVerbosity();
00066 
00067   try
00068   {
00069     Tabs tabs(0);
00070     {
00071       Tabs tab;
00072       Tabs tabz;
00073       SUNDANCE_MSG1(verb,
00074         tabs << "initializing product evaluator for " 
00075         << expr->toString());
00076 
00077       SUNDANCE_MSG2(verb,
00078         tab << "return sparsity " << std::endl
00079         << tabz << *(this->sparsity)());
00080 
00081       SUNDANCE_MSG2(verb,
00082         tab << "left sparsity " << std::endl 
00083         << tabz << *(leftSparsity()) << std::endl
00084         << tabz << "right sparsity " << std::endl 
00085         << tabz << *(rightSparsity()));
00086   
00087       SUNDANCE_MSG3(verb,
00088         tab << "left vector index map " 
00089         << leftEval()->vectorIndexMap() << std::endl
00090         << tabz << "right vector index map " 
00091         << rightEval()->vectorIndexMap() << std::endl
00092         << tabz << "left constant index map " 
00093         << leftEval()->constantIndexMap() << std::endl
00094         << tabz << "right constant index map " 
00095         << rightEval()->constantIndexMap());
00096     }                
00097     int vecResultIndex = 0;
00098     int constResultIndex = 0;
00099 
00100     for (int i=0; i<this->sparsity()->numDerivs(); i++)
00101     {
00102       Tabs tab0;
00103       const MultipleDeriv& d = this->sparsity()->deriv(i);
00104 
00105       SUNDANCE_MSG2(verb,
00106         tabs << std::endl 
00107         << tabs << "finding rules for deriv " << d);
00108 
00109       int order = d.order();
00110 
00111       /* Determine the index into which the result will be written */
00112       bool resultIsConstant = this->sparsity()->state(i)==ConstantDeriv; 
00113       resultIsConstant_[order].append(resultIsConstant);
00114       if (resultIsConstant)
00115       {
00116         SUNDANCE_MSG3(verb,
00117           tab0 << std::endl 
00118           << tab0 << "result will be in constant index " << constResultIndex);
00119         resultIndex_[order].append(constResultIndex);
00120         addConstantIndex(i, constResultIndex);
00121         constResultIndex++;
00122       }
00123       else
00124       {
00125         SUNDANCE_MSG3(verb,
00126           tab0 << std::endl 
00127           << tab0 << "result will be in constant index " << vecResultIndex);
00128         resultIndex_[order].append(vecResultIndex);
00129         addVectorIndex(i, vecResultIndex);
00130         vecResultIndex++;
00131       }
00132 
00133       /* If possible, we want to do the calculations in-place, writing into
00134        * one of the two operand's results vectors for the same derivative.
00135        * Provided that we process derivatives in descending order, it is
00136        * safe to destroy the operands' result vectors.
00137        */
00138        
00139       int dnLeftIndex = leftSparsity()->getIndex(d);
00140       int dnRightIndex = rightSparsity()->getIndex(d);
00141 
00142       
00143       bool hasVectorWorkspace = false;
00144       bool workspaceIsLeft = false;
00145       int workspaceIndex = -1;
00146       int workspaceCoeffIndex = -1;
00147       bool workspaceCoeffIsConstant = false;
00148 
00149 
00150       bool dnLeftIsConst = false;
00151       if (dnLeftIndex != -1) 
00152       {
00153         dnLeftIsConst = leftSparsity()->state(dnLeftIndex)==ConstantDeriv;
00154       }
00155       bool dnRightIsConst = false;
00156       if (dnRightIndex != -1)
00157       {
00158         dnRightIsConst = rightSparsity()->state(dnRightIndex)==ConstantDeriv;
00159       }
00160 
00161       /* First try to use the left result as a workspace */
00162       if (dnLeftIndex != -1 && !dnLeftIsConst 
00163         && rightSparsity()->containsDeriv(MultipleDeriv()))
00164       {
00165         /* We can write onto left vector */
00166         hasVectorWorkspace = true;
00167         workspaceIndex = leftEval()->vectorIndexMap().get(dnLeftIndex);       
00168         SUNDANCE_MSG3(verb,
00169           tab0 << "using left as workspace");
00170         workspaceIsLeft = true;
00171         int d0RightIndex = rightSparsity()->getIndex(MultipleDeriv());
00172         bool d0RightIsConst = rightSparsity()->state(d0RightIndex)==ConstantDeriv;
00173         workspaceCoeffIsConstant = d0RightIsConst;
00174         if (d0RightIsConst)
00175         {
00176           workspaceCoeffIndex 
00177             = rightEval()->constantIndexMap().get(d0RightIndex);
00178         }
00179         else
00180         {
00181           workspaceCoeffIndex 
00182             = rightEval()->vectorIndexMap().get(d0RightIndex);
00183         }
00184       }
00185 
00186       /* If the left didn't provide a workspace, try the right */
00187       if (!hasVectorWorkspace && dnRightIndex != -1 && !dnRightIsConst
00188         && leftSparsity()->containsDeriv(MultipleDeriv()))
00189       {
00190         /* We can write onto right vector */
00191         hasVectorWorkspace = true;
00192         workspaceIndex = rightEval()->vectorIndexMap().get(dnRightIndex); 
00193         workspaceIsLeft = false;
00194         SUNDANCE_MSG3(verb,
00195           tab0 << "using right as workspace");
00196         int d0LeftIndex = leftSparsity()->getIndex(MultipleDeriv());
00197         bool d0LeftIsConst = leftSparsity()->state(d0LeftIndex)==ConstantDeriv;
00198         workspaceCoeffIsConstant = d0LeftIsConst;
00199         if (d0LeftIsConst)
00200         {
00201           workspaceCoeffIndex 
00202             = leftEval()->constantIndexMap().get(d0LeftIndex);
00203         }
00204         else
00205         {
00206           workspaceCoeffIndex 
00207             = leftEval()->vectorIndexMap().get(d0LeftIndex);
00208         }
00209       }
00210       
00211       if (hasVectorWorkspace && verb > 2)
00212       {
00213         std::string wSide = "right";
00214         MultipleDeriv wsDeriv;
00215         if (workspaceIsLeft) 
00216         {
00217           wSide = "left";
00218           wsDeriv = leftSparsity()->deriv(dnLeftIndex);
00219         }
00220         else
00221         {
00222           wsDeriv = rightSparsity()->deriv(dnRightIndex);
00223         }
00224         SUNDANCE_MSG2(verb, tab0 << "has workspace vector: "
00225           << wSide << " deriv= " 
00226           << wsDeriv
00227           << ", coeff index= " << workspaceCoeffIndex);
00228       }
00229       else
00230       {
00231         SUNDANCE_MSG2(verb, tab0 << "has no workspace vector");
00232       }
00233 
00234       hasWorkspace_[order].append(hasVectorWorkspace);
00235       workspaceIsLeft_[order].append(workspaceIsLeft);
00236       workspaceIndex_[order].append(workspaceIndex);
00237       workspaceCoeffIndex_[order].append(workspaceCoeffIndex);
00238       workspaceCoeffIsConstant_[order].append(workspaceCoeffIsConstant);
00239       
00240       ProductRulePerms perms;
00241       d.productRulePermutations(perms);
00242       SUNDANCE_MSG4(verb,
00243         tabs << "product rule permutations " << perms);
00244 
00245       Array<Array<int> > ccTerms;
00246       Array<Array<int> > cvTerms;
00247       Array<Array<int> > vcTerms;
00248       Array<Array<int> > vvTerms;
00249       Array<int> startingVector;
00250       ProductParity startingParity;
00251 
00252       bool hasStartingVector = false;
00253 
00254       for (ProductRulePerms::const_iterator 
00255              iter = perms.begin(); iter != perms.end(); iter++)
00256       {
00257         Tabs tab1;
00258         MultipleDeriv dLeft = iter->first.first();
00259         MultipleDeriv dRight = iter->first.second();
00260         int multiplicity = iter->second;
00261           
00262         /* skip this combination if we've already pulled it out 
00263          * for workspace */
00264         if (hasVectorWorkspace && workspaceIsLeft 
00265           && dLeft.order()==order) continue;
00266         if (hasVectorWorkspace && !workspaceIsLeft 
00267           && dRight.order()==order) continue;
00268 
00269         if (!leftSparsity()->containsDeriv(dLeft)
00270           || !rightSparsity()->containsDeriv(dRight)) continue;
00271         int iLeft = leftSparsity()->getIndex(dLeft);
00272         int iRight = rightSparsity()->getIndex(dRight);
00273 
00274         if (iLeft==-1 || iRight==-1) continue;
00275         SUNDANCE_MSG4(verb,
00276           tab1 << "left deriv=" << dLeft);
00277         SUNDANCE_MSG4(verb,
00278           tab1 << "right deriv=" << dRight);
00279 
00280         bool leftIsConst = leftSparsity()->state(iLeft)==ConstantDeriv;
00281         bool rightIsConst = rightSparsity()->state(iRight)==ConstantDeriv;
00282 
00283         if (leftIsConst)
00284         {
00285           Tabs tab2;
00286           SUNDANCE_MSG4(verb,
00287             tab2 << "left is const");
00288           int leftIndex = leftEval()->constantIndexMap().get(iLeft);
00289           if (rightIsConst)
00290           {
00291             SUNDANCE_MSG4(verb,
00292               tab2 << "right is const");
00293             int rightIndex = rightEval()->constantIndexMap().get(iRight);
00294             ccTerms.append(tuple(leftIndex, rightIndex, multiplicity));
00295           }
00296           else
00297           {
00298             SUNDANCE_MSG4(verb,
00299               tab2 << "right is vec");
00300             int rightIndex = rightEval()->vectorIndexMap().get(iRight);
00301             if (!hasVectorWorkspace && !hasStartingVector)
00302             {
00303               SUNDANCE_MSG4(verb,
00304                 tab1 << "found c-v starting vec");
00305               startingVector = tuple(leftIndex, rightIndex, 
00306                 multiplicity);
00307               hasStartingVector = true;
00308               startingParity = ConstVec;
00309             }
00310             else
00311             {
00312               SUNDANCE_MSG4(verb,
00313                 tab1 << "found c-v term");
00314               cvTerms.append(tuple(leftIndex, rightIndex, 
00315                   multiplicity));
00316             }
00317           }
00318         }
00319         else
00320         {
00321           Tabs tab2;
00322           SUNDANCE_MSG4(verb,
00323             tab2 << "left is vec");
00324           int leftIndex = leftEval()->vectorIndexMap().get(iLeft);
00325           if (rightIsConst)
00326           {
00327             SUNDANCE_MSG4(verb,
00328               tab2 << "right is const");
00329             int rightIndex = rightEval()->constantIndexMap().get(iRight);
00330             if (!hasVectorWorkspace && !hasStartingVector)
00331             {
00332               SUNDANCE_MSG4(verb,
00333                 tab1 << "found v-c starting vec");
00334               startingVector = tuple(leftIndex, rightIndex, 
00335                 multiplicity);
00336               hasStartingVector = true;
00337               startingParity = VecConst;
00338             }
00339             else
00340             {
00341               SUNDANCE_MSG4(verb,
00342                 tab1 << "found v-c term");
00343               vcTerms.append(tuple(leftIndex, rightIndex, 
00344                   multiplicity));
00345             }
00346           }
00347           else
00348           {
00349             SUNDANCE_MSG4(verb,
00350               tab2 << "right is vec");
00351             int rightIndex = rightEval()->vectorIndexMap().get(iRight);
00352             if (!hasVectorWorkspace && !hasStartingVector)
00353             {
00354               SUNDANCE_MSG4(verb,
00355                 tab1 << "found v-v starting vec");
00356               startingVector = tuple(leftIndex, rightIndex, 
00357                 multiplicity);
00358               hasStartingVector = true;
00359               startingParity = VecVec;
00360             }
00361             else
00362             {
00363               SUNDANCE_MSG4(verb,
00364                 tab1 << "found v-v term");
00365               vvTerms.append(tuple(leftIndex, rightIndex, 
00366                   multiplicity));
00367             }
00368           }
00369         }
00370       }
00371       ccTerms_[order].append(ccTerms);
00372       cvTerms_[order].append(cvTerms);
00373       vcTerms_[order].append(vcTerms);
00374       vvTerms_[order].append(vvTerms);
00375       startingVectors_[order].append(startingVector);
00376       startingParities_[order].append(startingParity);
00377 
00378       if (verb > 2)
00379       {
00380         Tabs tab0;
00381         Out::os() << tab0 << "deriv " << i << " order=" << order ;
00382         if (resultIsConstant)
00383         {
00384           Out::os() << " constant result, index= ";
00385         }
00386         else
00387         {
00388           Out::os() << " vector result, index= ";
00389         }
00390         Out::os() << resultIndex_[order] << std::endl;
00391         {
00392           Tabs tab1;
00393           if (hasStartingVector) 
00394           {
00395             Out::os() << tab1 << "starting vector " << startingVector << std::endl;
00396           }
00397           Out::os() << tab1 << "c-c terms " << ccTerms << std::endl;
00398           Out::os() << tab1 << "c-v terms " << cvTerms << std::endl;
00399           Out::os() << tab1 << "v-c terms " << vcTerms << std::endl;
00400           Out::os() << tab1 << "v-v terms " << vvTerms << std::endl;
00401         }
00402       }
00403     }
00404 
00405     if (verb > 2)
00406     {
00407       Out::os() << tabs << "maps: " << std::endl;
00408       Out::os() << tabs << "vector index map " << vectorIndexMap() << std::endl;
00409       Out::os() << tabs << "constant index map " << constantIndexMap() << std::endl;
00410     }
00411   }
00412   catch(std::exception& e)
00413   {
00414     TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, 
00415       "exception detected in ProductEvaluator: expr="
00416       << expr->toString() << std::endl
00417       << "exception=" << e.what());
00418   }
00419 }
00420 
00421 void ProductEvaluator
00422 ::internalEval(const EvalManager& mgr,
00423   Array<double>& constantResults,
00424   Array<RCP<EvalVector> >& vectorResults) const
00425 {
00426   Tabs tabs(0);
00427 
00428   SUNDANCE_MSG1(mgr.verb(),
00429     tabs << "ProductEvaluator::eval() expr=" 
00430     << expr()->toString());
00431 
00432   /* evaluate the children */
00433   Array<RCP<EvalVector> > leftVectorResults; 
00434   Array<RCP<EvalVector> > rightVectorResults; 
00435   Array<double> leftConstantResults;
00436   Array<double> rightConstantResults;
00437   evalChildren(mgr, leftConstantResults, leftVectorResults,
00438     rightConstantResults, rightVectorResults);
00439 
00440   if (mgr.verb() > 2)
00441   {
00442     Out::os() << tabs << "left operand results" << std::endl;
00443     mgr.showResults(Out::os(), leftSparsity(), leftVectorResults,
00444       leftConstantResults);
00445     Out::os() << tabs << "right operand results" << std::endl;
00446     mgr.showResults(Out::os(), rightSparsity(), rightVectorResults,
00447       rightConstantResults);
00448   }
00449   
00450   constantResults.resize(this->sparsity()->numConstantDerivs());
00451   vectorResults.resize(this->sparsity()->numVectorDerivs());
00452 
00453   /* Evaluate from high to low differentiation order. This is necessary
00454    * so that we can do in-place evaluation of derivatives, overwriting
00455    * one of the operands' vectors */
00456 
00457   for (int order=maxOrder_; order>=0; order--)
00458   {
00459     for (int i=0; i<resultIndex_[order].size(); i++)
00460     {
00461       double constantVal = 0.0;
00462       const Array<Array<int> >& ccTerms = ccTerms_[order][i];
00463       for (int j=0; j<ccTerms.size(); j++)
00464       {
00465         /* add L*R*multiplicity to result */
00466         constantVal += leftConstantResults[ccTerms[j][0]] 
00467           * rightConstantResults[ccTerms[j][1]] * ccTerms[j][2];
00468       }
00469       /* If this derivative is a constant, we're done. */
00470       if (resultIsConstant_[order][i]) 
00471       {
00472         constantResults[resultIndex_[order][i]] = constantVal;
00473         continue;
00474       }
00475 
00476 
00477       /* For the vector case, the first thing to do is get storage
00478        * for the result. If we can reuse one of the operands' results
00479        * as workspace, great. If not, we'll need to allocate a new
00480        * vector. */
00481       RCP<EvalVector> result;
00482       if (hasWorkspace_[order][i])
00483       {
00484         int index = workspaceIndex_[order][i];
00485         int coeffIndex = workspaceCoeffIndex_[order][i];
00486         bool coeffIsConstant = workspaceCoeffIsConstant_[order][i];
00487         if (workspaceIsLeft_[order][i])
00488         {
00489           result = leftVectorResults[index];
00490           if (coeffIsConstant)
00491           {
00492             const double& coeff = rightConstantResults[coeffIndex];
00493             if (!isOne(coeff)) result->multiply_S(coeff);
00494           }
00495           else
00496           {
00497             const RCP<EvalVector>& coeff 
00498               = rightVectorResults[coeffIndex];
00499             result->multiply_V(coeff.get());
00500           }
00501         }
00502         else
00503         {
00504           result = rightVectorResults[index];
00505           if (coeffIsConstant)
00506           {
00507             const double& coeff = leftConstantResults[coeffIndex];
00508             if (!isOne(coeff)) result->multiply_S(coeff);
00509           }
00510           else
00511           {
00512             const RCP<EvalVector>& coeff 
00513               = leftVectorResults[coeffIndex];
00514             result->multiply_V(coeff.get());
00515           }
00516         }
00517         SUNDANCE_MSG5(mgr.verb(), tabs << "workspace = " << result->str());
00518       }
00519       else
00520       {
00521         result = mgr.popVector();
00522         const Array<int>& sv = startingVectors_[order][i];
00523         int multiplicity = sv[2];
00524         switch(startingParities_[order][i])
00525         {
00526           case VecVec:
00527             if (!isZero(constantVal))
00528             {
00529               if (!isOne(multiplicity))
00530               {
00531                 result->setTo_S_add_SVV(constantVal,
00532                   multiplicity,
00533                   leftVectorResults[sv[0]].get(),
00534                   rightVectorResults[sv[1]].get());
00535               }
00536               else
00537               {
00538                 result->setTo_S_add_VV(constantVal,
00539                   leftVectorResults[sv[0]].get(),
00540                   rightVectorResults[sv[1]].get());
00541               }
00542             }
00543             else
00544             {
00545               if (!isOne(multiplicity))
00546               {
00547                 result->setTo_SVV(multiplicity,
00548                   leftVectorResults[sv[0]].get(),
00549                   rightVectorResults[sv[1]].get());
00550               }
00551               else
00552               {
00553                 result->setTo_VV(leftVectorResults[sv[0]].get(),
00554                   rightVectorResults[sv[1]].get());
00555               }
00556             }
00557             SUNDANCE_MSG5(mgr.verb(), tabs << "init to v-v prod, m="
00558               << multiplicity << ", left=" 
00559               << leftVectorResults[sv[0]]->str()
00560               << ", right=" 
00561               << rightVectorResults[sv[1]]->str()
00562               << ", result=" << result->str());
00563             break;
00564           case VecConst:
00565             if (!isZero(constantVal))
00566             {
00567               if (!isOne(multiplicity*rightConstantResults[sv[1]]))
00568               {
00569                 result->setTo_S_add_SV(constantVal,
00570                   multiplicity
00571                   *rightConstantResults[sv[1]],  
00572                   leftVectorResults[sv[0]].get());
00573               }
00574               else
00575               {
00576                 result->setTo_S_add_V(constantVal,
00577                   leftVectorResults[sv[0]].get());
00578               }
00579             }
00580             else
00581             {
00582               if (!isOne(multiplicity*rightConstantResults[sv[1]]))
00583               {
00584                 result->setTo_SV(multiplicity
00585                   *rightConstantResults[sv[1]],  
00586                   leftVectorResults[sv[0]].get());
00587               }
00588               else
00589               {
00590                 result->setTo_V(leftVectorResults[sv[0]].get());
00591               }
00592             }
00593             SUNDANCE_MSG5(mgr.verb(), tabs << "init to v-c prod, m="
00594               << multiplicity << ", left=" 
00595               << leftVectorResults[sv[0]]->str()
00596               << ", right=" 
00597               << rightConstantResults[sv[1]]
00598               << ", result=" << result->str());
00599             break;
00600           case ConstVec:
00601             if (!isZero(constantVal))
00602             {
00603               if (!isOne(multiplicity*leftConstantResults[sv[0]]))
00604               {
00605                 result->setTo_S_add_SV(constantVal,
00606                   multiplicity
00607                   *leftConstantResults[sv[0]],  
00608                   rightVectorResults[sv[1]].get());
00609               }
00610               else
00611               {
00612                 result->setTo_S_add_V(constantVal,  
00613                   rightVectorResults[sv[1]].get());
00614               }
00615             }
00616             else
00617             {
00618               if (!isOne(multiplicity*leftConstantResults[sv[0]]))
00619               {
00620                 result->setTo_SV(multiplicity
00621                   *leftConstantResults[sv[0]],  
00622                   rightVectorResults[sv[1]].get());
00623               }
00624               else
00625               {
00626                 result->setTo_V(rightVectorResults[sv[1]].get());
00627               }
00628             }
00629             SUNDANCE_MSG5(mgr.verb(), tabs << "init to c-v prod, m="
00630               << multiplicity << ", left=" 
00631               << leftConstantResults[sv[0]]
00632               << ", right=" 
00633               << rightVectorResults[sv[1]]->str()
00634               << ", result=" << result->str());
00635                   
00636         }
00637         SUNDANCE_MSG4(mgr.verb(), tabs << "starting value = " << result->str());
00638       }
00639       vectorResults[resultIndex_[order][i]] = result;
00640 
00641       const Array<Array<int> >& cvTerms = cvTerms_[order][i];
00642       const Array<Array<int> >& vcTerms = vcTerms_[order][i];
00643       const Array<Array<int> >& vvTerms = vvTerms_[order][i];
00644 
00645       for (int j=0; j<cvTerms.size(); j++)
00646       {
00647         SUNDANCE_MSG4(mgr.verb(), tabs << "adding c-v term " << cvTerms[j]);
00648               
00649         double multiplicity = cvTerms[j][2];
00650         double scalar = multiplicity*leftConstantResults[cvTerms[j][0]];
00651         const EvalVector* vec = rightVectorResults[cvTerms[j][1]].get();
00652         if (!isOne(scalar))
00653         {
00654           result->add_SV(scalar, vec);
00655         }
00656         else
00657         {
00658           result->add_V(vec);
00659         }
00660       } 
00661 
00662       for (int j=0; j<vcTerms.size(); j++)
00663       {
00664         SUNDANCE_MSG4(mgr.verb(), tabs << "adding v-c term " << vcTerms[j]);
00665 
00666         double multiplicity = vcTerms[j][2];
00667         double scalar = multiplicity*rightConstantResults[vcTerms[j][1]];
00668         const EvalVector* vec = leftVectorResults[vcTerms[j][0]].get();
00669         if (!isOne(scalar))
00670         {
00671           result->add_SV(scalar, vec);
00672         }
00673         else
00674         {
00675           result->add_V(vec);
00676         }
00677       }
00678 
00679       for (int j=0; j<vvTerms.size(); j++)
00680       {
00681         SUNDANCE_MSG4(mgr.verb(), tabs << "adding v-v term " << vvTerms[j]);
00682 
00683         double multiplicity = vvTerms[j][2];
00684         const EvalVector* vec1 = leftVectorResults[vvTerms[j][0]].get();
00685         const EvalVector* vec2 = rightVectorResults[vvTerms[j][1]].get();
00686         if (!isOne(multiplicity))
00687         {
00688           result->add_SVV(multiplicity, vec1, vec2);
00689         }
00690         else
00691         {
00692           result->add_VV(vec1, vec2);
00693         }
00694       }
00695 
00696           
00697     }
00698   }
00699 
00700   if (mgr.verb() > 1)
00701   {
00702     Out::os() << tabs << "product result " << std::endl;
00703     mgr.showResults(Out::os(), this->sparsity(), vectorResults,
00704       constantResults);
00705   }
00706 }

Site Contact