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

Site Contact