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

Site Contact