void WaitPhase::calculate(EvalContext context) { if (context.ib()->rule_exec->phase == m_data->phase) { children().back()->eval(context); forward(children().back()); } }
Set<MultiSet<int> > ProductExpr::internalFindQ_V(int order, const EvalContext& context) const { Tabs tab0(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tab0 << "ProdExpr::internalFindQ_V(" << order << ")"); Set<MultiSet<int> > rtn; if (order > 1) return rtn; const Set<MultipleDeriv>& vLeft = leftEvaluatable()->findV(0, context); const Set<MultipleDeriv>& vRight = rightEvaluatable()->findV(0, context); if (order==0) { if (vLeft.size() > 0) { rtn.put(makeMultiSet<int>(0)); } if (vRight.size() > 0) { rtn.put(makeMultiSet<int>(1)); } } if (order==1) { if (vLeft.size() > 0) rtn.put(makeMultiSet<int>(1)); if (vRight.size() > 0) rtn.put(makeMultiSet<int>(0)); } SUNDANCE_MSG2(verb, tab0 << "Q_V[" << order << "]=" << rtn); return rtn; }
Set<MultipleDeriv> DiffOp::internalFindC(int order, const EvalContext& context) const { Tabs tabs(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tabs << "DiffOp::internalFindC() for " << toString()); Set<MultipleDeriv> rtn ; { Tabs tab1; SUNDANCE_MSG5(verb, tab1 << "finding R"); const Set<MultipleDeriv>& R = findR(order, context); SUNDANCE_MSG5(verb, tab1 << "finding V"); const Set<MultipleDeriv>& V = findV(order, context); /** Call findC() to ensure that the argument has C tabulated */ evaluatableArg()->findC(order, context); SUNDANCE_MSG5(verb, tab1 << "R=" << R); SUNDANCE_MSG5(verb, tab1 << "V=" << V); rtn = R.setDifference(V); SUNDANCE_MSG3(verb, tabs << "C[" << order << "]=" << rtn); } SUNDANCE_MSG2(verb, tabs << "C[" << order << "]=R\\V = " << rtn); SUNDANCE_MSG2(verb, tabs << "done with DiffOp::internalFindC for " << toString()); return rtn; }
Set<MultipleDeriv> ExplicitFunctionalDerivativeElement ::internalFindC(int order, const EvalContext& context) const { Tabs tabs(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tabs << "ExplicitFunctionalDerivativeElement::internalFindC() for " << toString()); Set<MultipleDeriv> rtn ; if (order < 3) { Tabs tab1; SUNDANCE_MSG5(verb, tab1 << "finding R"); const Set<MultipleDeriv>& R = findR(order, context); SUNDANCE_MSG5(verb, tab1 << "R=" << R); SUNDANCE_MSG5(verb, tab1 << "finding C for arg"); const Set<MultipleDeriv>& argC = evaluatableArg()->findC(order+1, context); SUNDANCE_MSG5(verb, tab1 << "argC=" << argC); MultipleDeriv me(fd_); Set<MultipleDeriv> tmp = setDivision(argC, makeSet(me)); rtn = tmp.intersection(R); } SUNDANCE_MSG2(verb, tabs << "C[" << order << "]=" << rtn); SUNDANCE_MSG2(verb, tabs << "done with ExplicitFunctionalDerivativeElement::internalFindC for " << toString()); return rtn; }
Set<MultipleDeriv> ExplicitFunctionalDerivativeElement ::internalFindW(int order, const EvalContext& context) const { Tabs tab0(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tab0 << "ExplicitFunctionalDerivativeElement::internalFindW(order=" << order << ") for " << toString()); Set<MultipleDeriv> rtn ; if (order < 3) { Tabs tab1; const Set<MultipleDeriv>& WArgPlus = evaluatableArg()->findW(order+1, context); SUNDANCE_MSG5(verb, tab1 << "WArgPlus = " << WArgPlus); MultipleDeriv me(fd_); Set<MultipleDeriv> WargPlusOslashFD = setDivision(WArgPlus, makeSet(me)); SUNDANCE_MSG5(verb, tab1 << "WArgPlus / fd = " << WargPlusOslashFD); rtn = WargPlusOslashFD; } SUNDANCE_MSG2(verb, tab0 << "W[" << order << "]=" << rtn); SUNDANCE_MSG2(verb, tab0 << "done with ExplicitFunctionalDerivativeElement::internalFindW(" << order << ") for " << toString()); return rtn; }
void EvaluatableExpr::setupEval(const EvalContext& context) const { Tabs tabs0(0); int verb = context.evalSetupVerbosity(); SUNDANCE_MSG1(verb, tabs0 << "setupEval() for " << this->toString()); if (!evaluators_.containsKey(context)) { Tabs tabs; SUNDANCE_MSG2(verb, tabs << "creating new evaluator..."); SUNDANCE_MSG2(verb, tabs << "my sparsity superset = " << std::endl << *sparsitySuperset(context)); RCP<Evaluator> eval; if (sparsitySuperset(context)->numDerivs()>0) { SUNDANCE_MSG2(verb, tabs << "calling createEvaluator()"); eval = rcp(createEvaluator(this, context)); } else { SUNDANCE_MSG2(verb, tabs << "EE: no results needed... creating null evaluator"); eval = rcp(new NullEvaluator()); } evaluators_.put(context, eval); } else { Tabs tabs; SUNDANCE_MSG2(verb, tabs << "reusing existing evaluator..."); } }
Set<MultipleDeriv> DiffOp::internalFindW(int order, const EvalContext& context) const { Tabs tabs(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tabs << "DiffOp::internalFindW(order=" << order << ") for " << toString()); Set<MultipleDeriv> rtn ; if (order <= 2) { Tabs tab1; const Set<MultipleDeriv>& W1 = evaluatableArg()->findW(1, context); const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context); const Set<MultipleDeriv>& WArgPlus = evaluatableArg()->findW(order+1, context); SUNDANCE_MSG5(verb, tab1 << "W1 = " << W1); SUNDANCE_MSG5(verb, tab1 << "WArg = " << WArg); SUNDANCE_MSG5(verb, tab1 << "WArgPlus = " << WArgPlus); Set<MultipleDeriv> Tx = applyTx(WArg, mi_); Set<MultipleDeriv> ZXx = applyZx(W1, mi_).setUnion(Xx(mi_)); SUNDANCE_MSG5(verb, tab1 << "Tx(Warg) = " << Tx); SUNDANCE_MSG5(verb, tab1 << "ZXx(W1) = " << ZXx); Set<MultipleDeriv> WargPlusOslashZXx = setDivision(WArgPlus, ZXx); SUNDANCE_MSG5(verb, tab1 << "WArgPlus / ZXx = " << WargPlusOslashZXx); rtn = WargPlusOslashZXx.setUnion(Tx); } SUNDANCE_MSG3(verb, tabs << "W[" << order << "]=" << rtn); SUNDANCE_MSG3(verb, tabs << "done with DiffOp::internalFindW(" << order << ") for " << toString()); return rtn; }
void DiffOp::requestMultiIndexAtEvalPoint(const MultiIndex& mi, const MultipleDeriv& u, const EvalContext& context) const { int verb = context.setupVerbosity(); Tabs tab0(0); SUNDANCE_MSG3(verb, tab0 << "DiffOp::requestMultiIndexAtEvalPoint() for=" << toString()); TEUCHOS_TEST_FOR_EXCEPT(u.size() != 1); const Deriv& d = *(u.begin()); if (d.isFunctionalDeriv()) { const SpatialDerivSpecifier& sds = d.opOnFunc(); TEUCHOS_TEST_FOR_EXCEPTION(sds.isDivergence(), std::logic_error, "divergence operators not possible within DiffOp"); TEUCHOS_TEST_FOR_EXCEPTION(sds.isNormal(), std::logic_error, "normal deriv operators not possible within DiffOp"); const MultiIndex& newMi = sds.mi(); const SymbolicFuncElement* sfe = d.symbFuncElem(); TEUCHOS_TEST_FOR_EXCEPT(sfe == 0); const EvaluatableExpr* evalPt = sfe->evalPt(); const ZeroExpr* z = dynamic_cast<const ZeroExpr*>(evalPt); if (z != 0) return; const DiscreteFuncElement* df = dynamic_cast<const DiscreteFuncElement*>(evalPt); df->addMultiIndex(newMi); df->findW(1, context); df->findV(1, context); df->findC(1, context); } }
Value OrExpr::Evaluate(SymbolTable *scope, EvalContext& context, bool asbool) { // Scope override; must do this for every expression that might contain an identifier if(this->scope != NULL) scope = this->scope; // Lowering of A or B: // [A] // [iftrue goto end] // [B] // label end: String* value = new String(); string labelbase = context.GetUniqueLabelName(); Anchor* endanchor = new Anchor(labelbase + ".end"); // a value->Append( a->Evaluate(scope, context, true).ToCodeString() ); // iftrue goto end: value->Code("1B 03 FF FF FF FF"); value->AddReference(value->GetPos()-4, endanchor); // b value->Append( b->Evaluate(scope, context, true).ToCodeString() ); // end: value->AddAnchor(endanchor); return Value(value); }
void FinishPhase::calculate(EvalContext context) { map_calculate(children().back(), context); if (context.ib()->rule_exec->phase == m_data->phase) { finish(); } }
Set<MultipleDeriv> ConstantExpr::internalFindC(int order, const EvalContext& context) const { Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "ConstantExpr::internalFindC is forwarding to findR()"); return findR(order, context); }
Set<MultipleDeriv> ConstantExpr::internalFindV(int order, const EvalContext& context) const { Set<MultipleDeriv> rtn; Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "ConstantExpr::internalFindV is a no-op"); return rtn; }
Value Operator::value_calculate(Value v, EvalContext context) { static const char* c_capture_name = "predicate_operator_capture"; if (! m_data) { BOOST_THROW_EXCEPTION( einval() << errinfo_what( "Evaluation without pre evaluation!" ) ); } IronBee::Field capture = IronBee::Field::create_no_copy_list<void *>( context.memory_pool(), c_capture_name, sizeof(c_capture_name) - 1, List<void *>::create(context.memory_pool()) ); int success = 0; try { success = m_data->op.execute_instance( m_data->instance_data, context, v, capture ); } catch (const error& e) { string old_what = *boost::get_error_info<errinfo_what>(e); e << errinfo_what( "Predicate operator failure for " + to_s() + " : " + old_what ); throw e; } if (success) { return capture; } else { return Value(); } }
Set<MultipleDeriv> UnknownParameterElement::internalFindV(int order, const EvalContext& context) const { Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "UPE::internalFindV is a no-op"); Set<MultipleDeriv> rtn; return rtn; }
Set<MultipleDeriv> ZeroExpr::internalFindC(int order, const EvalContext& context) const { Set<MultipleDeriv> rtn; Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "ZeroExpr::internalFindC found" << rtn << " for order=" << order); return rtn; }
Value Transformation::value_calculate(Value v, EvalContext context) { if (! m_data) { BOOST_THROW_EXCEPTION( einval() << errinfo_what( "Reset without pre evaluation!" ) ); } return m_data->transformation.execute(context.memory_pool(), v); }
RCP<Array<Set<MultipleDeriv> > > ExplicitFunctionalDerivativeElement ::internalDetermineR(const EvalContext& context, const Array<Set<MultipleDeriv> >& RInput) const { Tabs tab0(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tab0 << "ExplicitFunctionalDerivativeElement::internalDetermineR for=" << toString()); SUNDANCE_MSG2(verb, tab0 << "RInput = " << RInput ); RCP<Array<Set<MultipleDeriv> > > rtn = rcp(new Array<Set<MultipleDeriv> >(RInput.size())); { Tabs tab1; for (int i=0; i<RInput.size(); i++) { Tabs tab2; const Set<MultipleDeriv>& Wi = findW(i, context); SUNDANCE_MSG5(verb, tab2 << "W[" << i << "] = " << Wi ); (*rtn)[i] = RInput[i].intersection(Wi); } Array<Set<MultipleDeriv> > RArg(RInput.size()+1); MultipleDeriv me(fd_); for (int order=1; order<=RInput.size(); order++) { Tabs tab2; SUNDANCE_MSG3(verb, tab2 << "order = " << order); if (RInput[order-1].size() == 0) continue; const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context); const Set<MultipleDeriv>& RMinus = (*rtn)[order-1]; SUNDANCE_MSG3(verb, tab2 << "RInput = " << RInput[order-1]); SUNDANCE_MSG3(verb, tab2 << "FD times RInput = " << setProduct(RMinus, makeSet(me))); RArg[order].merge(setProduct(RMinus, makeSet(me)).intersection(WArg)); } SUNDANCE_MSG3(verb, tab1 << "RArg = " << RArg); SUNDANCE_MSG3(verb, tab1 << "calling determineR() for arg " << evaluatableArg()->toString()); evaluatableArg()->determineR(context, RArg); } printR(verb, rtn); SUNDANCE_MSG2(verb, tab0 << "done with ExplicitFunctionalDerivativeElement::internalDetermineR for " << toString()); /* all done */ return rtn; }
Set<MultipleDeriv> ConstantExpr::internalFindW(int order, const EvalContext& context) const { Set<MultipleDeriv> rtn; if (order==0) rtn.put(MultipleDeriv()); Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "ConstantExpr::internalFindW found" << rtn << " for order=" << order); return rtn; }
RCP<SparsitySuperset> EvaluatableExpr::sparsitySuperset(const EvalContext& context) const { Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "getting sparsity superset for " << toString()); RCP<SparsitySuperset> rtn; if (sparsity_.containsKey(context)) { Tabs tab1; SUNDANCE_MSG2(context.setupVerbosity(), tab1 << "reusing previously computed data..."); rtn = sparsity_.get(context); } else { Tabs tab1; SUNDANCE_MSG2(context.setupVerbosity(), tab1 << "computing from scratch..."); const Set<MultipleDeriv>& R = findR(context); const Set<MultipleDeriv>& C = findC(context); const Set<MultipleDeriv>& V = findV(context); if (context.setupVerbosity() > 4) { Out::os() << tab1 << "R=" << R << endl; Out::os() << tab1 << "C=" << C << endl; Out::os() << tab1 << "V=" << V << endl; } rtn = rcp(new SparsitySuperset(C.intersection(R), V.intersection(R))); sparsity_.put(context, rtn); } return rtn; }
Value AndExpr::Evaluate(SymbolTable *scope, EvalContext& context, bool asbool) { // Scope override; must do this for every expression that might contain an identifier if(this->scope != NULL) scope = this->scope; // Lowering A and B: // [A] // [iffalse goto end] // [B] // label end: String* value = new String(); // Create internal label string labelbase = context.GetUniqueLabelName(); Anchor* endanchor = new Anchor(labelbase + ".end"); // Evaluate the first operand value->Append( a->Evaluate(scope, context, true).ToCodeString() ); // Add a jump to the end if the first operand is false value->Code("1B 02 FF FF FF FF"); value->AddReference(value->GetPos()-4, endanchor); // TODO: // Hm. I just realized that some boolean expressions (and and or) rely on reference // resolution to operate correctly. Thus, it doesn't make sense to use them in ROM // write statements at the moment, because ROM write statements occur after normal // resolution, but without doing any resolution themselves. Perhaps ROM write statements // should have a special resolution step to take care of stuff like this. (Perhaps // the ROM data itself should be represented as a ByteChunk, with refs?) // Anyway, don't worry about this for now, since using boolean expressions in a ROM // write statement is not a very likely usage scenario. // UPDATE: 11/11/2008 // This issue has been fixed by moving the evaluation of ROM write subexpressions // back to the evaluation pass of the compiler, and simply caching the results and // resolving references in a later pass. However, it still might be worthwhile to // consider alternative solutions; whole-ROM resolution seems interesting for example. // Evaluate the second operand value->Append( b->Evaluate(scope, context, true).ToCodeString() ); // Set the position of the end label value->AddAnchor(endanchor); return Value(value); }
Set<MultipleDeriv> DiffOp::internalFindV(int order, const EvalContext& context) const { Tabs tabs(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tabs << "DiffOp::internalFindV(" << order << ") for " << toString()); Set<MultipleDeriv> rtn; if (order <= 2) { Tabs tab1; const Set<MultipleDeriv>& W1 = evaluatableArg()->findW(1, context); const Set<MultipleDeriv>& VArg = evaluatableArg()->findV(order, context); const Set<MultipleDeriv>& VArgPlus = evaluatableArg()->findV(order+1, context); const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context); const Set<MultipleDeriv>& WArgPlus = evaluatableArg()->findW(order+1, context); SUNDANCE_MSG5(verb, tab1 << "W1=" << W1); SUNDANCE_MSG5(verb, tab1 << "VArg=" << VArg); SUNDANCE_MSG5(verb, tab1 << "VArgPlus=" << VArgPlus); SUNDANCE_MSG5(verb, tab1 << "WArg=" << WArg); SUNDANCE_MSG5(verb, tab1 << "WArgPlus=" << WArgPlus); Set<MultipleDeriv> Tx = applyTx(VArg, mi_); Set<MultipleDeriv> Zx = applyZx(W1, mi_); SUNDANCE_MSG5(verb, tab1 << "Tx(Varg) = " << Tx); SUNDANCE_MSG5(verb, tab1 << "Zx(W1) = " << Zx); Set<MultipleDeriv> WargPlusOslashZx = setDivision(WArgPlus, Zx); Set<MultipleDeriv> VargPlusOslashXx = setDivision(VArgPlus, Xx(mi_)); SUNDANCE_MSG5(verb, tab1 << "WArgPlus / Z_alpha = " << WargPlusOslashZx); SUNDANCE_MSG5(verb, tab1 << "VArgPlus / X_alpha = " << VargPlusOslashXx); rtn = WargPlusOslashZx.setUnion(VargPlusOslashXx).setUnion(Tx); SUNDANCE_MSG5(verb, tab1 << "WArgPlus/Z union VArgPlus/X union T =" << rtn); rtn = rtn.intersection(findR(order, context)); } SUNDANCE_MSG2(verb, tabs << "V[" << order << "]=" << rtn); SUNDANCE_MSG2(verb, tabs << "done with DiffOp::internalFindV(" << order << ") for " << toString()); return rtn; }
Set<MultiSet<int> > ProductExpr::internalFindQ_W(int order, const EvalContext& context) const { Tabs tab0(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tab0 << "ProdExpr::internalFindQ_W(" << order << ")"); Set<MultiSet<int> > rtn; if (order > 2) return rtn; if (order==2) { rtn.put(makeMultiSet<int>(0,1)); return rtn; } Tabs tab1; SUNDANCE_MSG3(verb, tab1 << "calling findW(0) for left"); const Set<MultipleDeriv>& wLeft = leftEvaluatable()->findW(0, context); SUNDANCE_MSG3(verb, tab1 << "found wLeft(0)=" << wLeft); SUNDANCE_MSG3(verb, tab1 << "calling findW(0) for right"); const Set<MultipleDeriv>& wRight = rightEvaluatable()->findW(0, context); SUNDANCE_MSG3(verb, tab1 << "found wRight(0)=" << wRight); if (order==0) { if (wLeft.size() > 0) { rtn.put(makeMultiSet<int>(0)); } if (wRight.size() > 0) { rtn.put(makeMultiSet<int>(1)); } } if (order==1) { if (wLeft.size() > 0) rtn.put(makeMultiSet<int>(1)); if (wRight.size() > 0) rtn.put(makeMultiSet<int>(0)); } SUNDANCE_MSG2(verb, tab0 << "Q_W[" << order << "]=" << rtn); return rtn; }
Set<MultipleDeriv> UnknownParameterElement::internalFindW(int order, const EvalContext& context) const { Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "in UPE::internalFindW, order=" << order); Set<MultipleDeriv> rtn; if (order==0) { if (!evalPtIsZero()) rtn.put(MultipleDeriv()); } else if (order==1) { MultipleDeriv md = makeMultiDeriv(funcDeriv(this)); rtn.put(md); } return rtn; }
Array<Set<MultipleDeriv> > EvaluatableExpr ::computeInputR(const EvalContext& context, const Array<Set<MultiSet<int> > >& funcIDCombinations, const Array<Set<MultiIndex> >& spatialDerivs) const { int verb = context.setupVerbosity(); Tabs tabs(0); SUNDANCE_MSG2(verb, tabs << "in EE::computeInputR()"); Array<Set<MultipleDeriv> > rtn(funcIDCombinations.size()); for (int order=0; order<funcIDCombinations.size(); order++) { Tabs tabs1; SUNDANCE_MSG2(verb, tabs << "order=" << order); SUNDANCE_MSG2(verb, tabs1 << "funcID combs=" << funcIDCombinations[order]); const Set<MultipleDeriv>& W = findW(order, context); SUNDANCE_MSG2(verb, tabs1 << "W[order=" << order << "]=" << W); for (Set<MultipleDeriv>::const_iterator i=W.begin(); i!=W.end(); i++) { Tabs tab2; const MultipleDeriv& nonzeroDeriv = *i; if (nonzeroDeriv.isInRequiredSet(funcIDCombinations[order], spatialDerivs[order])) { SUNDANCE_MSG2(verb, tab2 << "md=" << nonzeroDeriv << " added to inputR"); rtn[order].put(nonzeroDeriv); } else { SUNDANCE_MSG2(verb, tab2 << "md=" << nonzeroDeriv << " not needed"); } } } SUNDANCE_MSG2(verb, tabs << "inputR=" << rtn); return rtn; }
RCP<Array<Set<MultipleDeriv> > > EvaluatableExpr ::internalDetermineR(const EvalContext& context, const Array<Set<MultipleDeriv> >& RInput) const { Tabs tab0(0); int verb = context.setupVerbosity(); RCP<Array<Set<MultipleDeriv> > > rtn = rcp(new Array<Set<MultipleDeriv> >(RInput.size())); SUNDANCE_MSG2(verb, tab0 << "EE::internalDetermineR() for " << toString() ); SUNDANCE_MSG2(verb, tab0 << "RInput = " << RInput ); for (int i=0; i<RInput.size(); i++) { Tabs tab1; if (RInput[i].size()==0) continue; const Set<MultipleDeriv>& Wi = findW(i, context); SUNDANCE_MSG3(verb, tab1 << "W[" << i << "] = " << Wi ); (*rtn)[i] = RInput[i].intersection(Wi); } printR(verb, rtn); return rtn; }
Set<MultipleDeriv> ExplicitFunctionalDerivativeElement ::internalFindV(int order, const EvalContext& context) const { Tabs tabs(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tabs << "ExplicitFunctionalDerivativeElement::internalFindV(" << order << ") for " << toString()); Set<MultipleDeriv> rtn; { Tabs tab1; SUNDANCE_MSG5(verb, tab1 << "finding R"); const Set<MultipleDeriv>& R = findR(order, context); SUNDANCE_MSG5(verb, tab1 << "finding C"); const Set<MultipleDeriv>& C = findC(order, context); rtn = R.setDifference(C); } SUNDANCE_MSG2(verb, tabs << "V[" << order << "]=" << rtn); SUNDANCE_MSG2(verb, tabs << "done with ExplicitFunctionalDerivativeElement::internalFindV(" << order << ") for " << toString()); return rtn; }
CellDiameterExprEvaluator::CellDiameterExprEvaluator( const CellDiameterExpr* expr, const EvalContext& context) : SubtypeEvaluator<CellDiameterExpr>(expr, context), stringRep_(expr->toString()) { Tabs tabs; int verb = context.setupVerbosity(); SUNDANCE_MSG1(verb, tabs << "initializing cell diameter expr evaluator for " << expr->toString()); SUNDANCE_MSG2(verb, tabs << "return sparsity " << std::endl << *(this->sparsity)()); TEUCHOS_TEST_FOR_EXCEPTION(this->sparsity()->numDerivs() > 1, std::logic_error, "CellDiameterExprEvaluator ctor found a sparsity table " "with more than one entry. The bad sparsity table is " << *(this->sparsity)()); /* * There is only one possible entry in the nozeros table for a * cell diameter expression: a zeroth derivative. */ for (int i=0; i<this->sparsity()->numDerivs(); i++) { const MultipleDeriv& d = this->sparsity()->deriv(i); TEUCHOS_TEST_FOR_EXCEPTION(d.order()!=0, std::logic_error, "CellDiameterExprEvaluator ctor found an entry in the " "sparsity superset that is not a zeroth-order derivative. " "The bad entry is " << this->sparsity()->deriv(i) << ". The superset is " << *(this->sparsity)()); addVectorIndex(i, 0); } }
Value MenuExpr::Evaluate(SymbolTable* scope, EvalContext& context, bool asbool) { if(this->scope != NULL) scope = this->scope; // Lowering a menu statement: // [19 02][option][02] - for each option // [1C 0C $cols][11][12] // [09 $num (statementjmps)] // [goto end] // [statement][goto end] - for each statement // label end: String* value = new String(); // Create internal labels vector<Anchor*> anchors; string labelbase = context.GetUniqueLabelName(); for(unsigned int i = 0; i < options.size(); ++i) { std::stringstream ss; ss << ".opt" << i; Anchor* a = new Anchor(labelbase + ss.str()); anchors.push_back(a); } Anchor* endanchor = new Anchor(labelbase + ".end"); // First, append the options between [19 02] and [02] codes for(unsigned int i = 0; i < options.size(); ++i) { value->Code("19 02"); value->Append( options[i]->Evaluate(scope, context).ToCodeString() ); value->Code("02"); } // Next, append the option display commands // If we're only using two options, and no number of columns was specified, // use "1C 07", otherwise, use "1C 0C". if(options.size() == 2 && defcolumns) value->Code("1C 07"); else value->Code("1C 0C"); value->Byte(columns);// write exactly one byte for the column count value->Code("11 12"); // Next, the multi-jump code value->Code("09"); value->Byte(results.size());// write exactly one byte for the option count for(unsigned int i = 0; i < results.size(); ++i) { value->Code("FF FF FF FF"); value->AddReference(value->GetPos() - 4, anchors[i]); } // Add a jump to the "default" option after the multi-jump, or end if no default value->Code("0A FF FF FF FF"); if(defaultopt != -1) value->AddReference(value->GetPos() - 4, anchors[defaultopt]); else value->AddReference(value->GetPos() - 4, endanchor); // Finally, write out all the options, with a "goto end" after each // At each point we set the position of the relevant label. for(unsigned int i = 0; i < results.size(); ++i) { value->AddAnchor(anchors[i]); value->Append( results[i]->Evaluate(scope, context).ToCodeString() ); // Add a "goto end" after every statement, in case it falls through value->Code("0A FF FF FF FF"); value->AddReference(value->GetPos() - 4, endanchor); } // Last step: set position of the "end" label value->AddAnchor(endanchor); return Value(value); }
Value IfExpr::Evaluate(SymbolTable *env, EvalContext& context, bool asbool) { if(this->scope != NULL) env = this->scope; /* * Lowering an if statement: * * [condition] * [iffalse goto falselbl] * [thenstmt] * [goto endlbl] * falselbl: * [elsestmt] * endlbl: */ String* value = new String(); // Create internal labels string labelbase = context.GetUniqueLabelName(); Anchor* endanchor = new Anchor(labelbase + ".end"); Anchor* falseanchor = new Anchor(labelbase + ".false"); // First, we evaluate the condition Value cond_val = condition->Evaluate(env, context, true); // TODO: this might be an opportunity to do some typechecking on the returned value, // instead of just converting it to a string. Maybe some warnings would be appropriate? // (i.e., conditioning on a number value, which is almost always meaningless) // append cond_val to the output: value->Append(cond_val.ToCodeString()); // Then, we output an "iffalse goto false" instruction, and register a jump reference value->Code("1B 02 FF FF FF FF"); value->AddReference(value->GetSize() - 4, falseanchor); // Evaluate the "then" statement Value then_val = thenexpr->Evaluate(env, context); value->Append(then_val.ToCodeString()); // Add a "goto end" // TODO: strictly speaking, we can dispense with this last goto when // there is no 'else' clause. We'll leave it here for now until we // get the first round of regression tests in place, and then we'll // update it along with the other evaluation refactoring. value->Code("0A FF FF FF FF"); value->AddReference(value->GetPos() - 4, endanchor); // Set the position of the false anchor within the string value->AddAnchor(falseanchor); // Evaluate the "else" statement if(elseexpr) { Value else_val = elseexpr->Evaluate(env, context); value->Append(else_val.ToCodeString()); } // Set the position of the "end" label value->AddAnchor(endanchor); return Value(value); }
ProductEvaluator::ProductEvaluator(const ProductExpr* expr, const EvalContext& context) : BinaryEvaluator<ProductExpr>(expr, context), maxOrder_(this->sparsity()->maxOrder()), resultIndex_(maxOrder_+1), resultIsConstant_(maxOrder_+1), hasWorkspace_(maxOrder_+1), workspaceIsLeft_(maxOrder_+1), workspaceIndex_(maxOrder_+1), workspaceCoeffIndex_(maxOrder_+1), workspaceCoeffIsConstant_(maxOrder_+1), ccTerms_(maxOrder_+1), cvTerms_(maxOrder_+1), vcTerms_(maxOrder_+1), vvTerms_(maxOrder_+1), startingVectors_(maxOrder_+1), startingParities_(maxOrder_+1) { int verb = context.evalSetupVerbosity(); try { Tabs tabs(0); { Tabs tab; Tabs tabz; SUNDANCE_MSG1(verb, tabs << "initializing product evaluator for " << expr->toString()); SUNDANCE_MSG2(verb, tab << "return sparsity " << std::endl << tabz << *(this->sparsity)()); SUNDANCE_MSG2(verb, tab << "left sparsity " << std::endl << tabz << *(leftSparsity()) << std::endl << tabz << "right sparsity " << std::endl << tabz << *(rightSparsity())); SUNDANCE_MSG3(verb, tab << "left vector index map " << leftEval()->vectorIndexMap() << std::endl << tabz << "right vector index map " << rightEval()->vectorIndexMap() << std::endl << tabz << "left constant index map " << leftEval()->constantIndexMap() << std::endl << tabz << "right constant index map " << rightEval()->constantIndexMap()); } int vecResultIndex = 0; int constResultIndex = 0; for (int i=0; i<this->sparsity()->numDerivs(); i++) { Tabs tab0; const MultipleDeriv& d = this->sparsity()->deriv(i); SUNDANCE_MSG2(verb, tabs << std::endl << tabs << "finding rules for deriv " << d); int order = d.order(); /* Determine the index into which the result will be written */ bool resultIsConstant = this->sparsity()->state(i)==ConstantDeriv; resultIsConstant_[order].append(resultIsConstant); if (resultIsConstant) { SUNDANCE_MSG3(verb, tab0 << std::endl << tab0 << "result will be in constant index " << constResultIndex); resultIndex_[order].append(constResultIndex); addConstantIndex(i, constResultIndex); constResultIndex++; } else { SUNDANCE_MSG3(verb, tab0 << std::endl << tab0 << "result will be in constant index " << vecResultIndex); resultIndex_[order].append(vecResultIndex); addVectorIndex(i, vecResultIndex); vecResultIndex++; } /* If possible, we want to do the calculations in-place, writing into * one of the two operand's results vectors for the same derivative. * Provided that we process derivatives in descending order, it is * safe to destroy the operands' result vectors. */ int dnLeftIndex = leftSparsity()->getIndex(d); int dnRightIndex = rightSparsity()->getIndex(d); bool hasVectorWorkspace = false; bool workspaceIsLeft = false; int workspaceIndex = -1; int workspaceCoeffIndex = -1; bool workspaceCoeffIsConstant = false; bool dnLeftIsConst = false; if (dnLeftIndex != -1) { dnLeftIsConst = leftSparsity()->state(dnLeftIndex)==ConstantDeriv; } bool dnRightIsConst = false; if (dnRightIndex != -1) { dnRightIsConst = rightSparsity()->state(dnRightIndex)==ConstantDeriv; } /* First try to use the left result as a workspace */ if (dnLeftIndex != -1 && !dnLeftIsConst && rightSparsity()->containsDeriv(MultipleDeriv())) { /* We can write onto left vector */ hasVectorWorkspace = true; workspaceIndex = leftEval()->vectorIndexMap().get(dnLeftIndex); SUNDANCE_MSG3(verb, tab0 << "using left as workspace"); workspaceIsLeft = true; int d0RightIndex = rightSparsity()->getIndex(MultipleDeriv()); bool d0RightIsConst = rightSparsity()->state(d0RightIndex)==ConstantDeriv; workspaceCoeffIsConstant = d0RightIsConst; if (d0RightIsConst) { workspaceCoeffIndex = rightEval()->constantIndexMap().get(d0RightIndex); } else { workspaceCoeffIndex = rightEval()->vectorIndexMap().get(d0RightIndex); } } /* If the left didn't provide a workspace, try the right */ if (!hasVectorWorkspace && dnRightIndex != -1 && !dnRightIsConst && leftSparsity()->containsDeriv(MultipleDeriv())) { /* We can write onto right vector */ hasVectorWorkspace = true; workspaceIndex = rightEval()->vectorIndexMap().get(dnRightIndex); workspaceIsLeft = false; SUNDANCE_MSG3(verb, tab0 << "using right as workspace"); int d0LeftIndex = leftSparsity()->getIndex(MultipleDeriv()); bool d0LeftIsConst = leftSparsity()->state(d0LeftIndex)==ConstantDeriv; workspaceCoeffIsConstant = d0LeftIsConst; if (d0LeftIsConst) { workspaceCoeffIndex = leftEval()->constantIndexMap().get(d0LeftIndex); } else { workspaceCoeffIndex = leftEval()->vectorIndexMap().get(d0LeftIndex); } } if (hasVectorWorkspace && verb > 2) { std::string wSide = "right"; MultipleDeriv wsDeriv; if (workspaceIsLeft) { wSide = "left"; wsDeriv = leftSparsity()->deriv(dnLeftIndex); } else { wsDeriv = rightSparsity()->deriv(dnRightIndex); } SUNDANCE_MSG2(verb, tab0 << "has workspace vector: " << wSide << " deriv= " << wsDeriv << ", coeff index= " << workspaceCoeffIndex); } else { SUNDANCE_MSG2(verb, tab0 << "has no workspace vector"); } hasWorkspace_[order].append(hasVectorWorkspace); workspaceIsLeft_[order].append(workspaceIsLeft); workspaceIndex_[order].append(workspaceIndex); workspaceCoeffIndex_[order].append(workspaceCoeffIndex); workspaceCoeffIsConstant_[order].append(workspaceCoeffIsConstant); ProductRulePerms perms; d.productRulePermutations(perms); SUNDANCE_MSG4(verb, tabs << "product rule permutations " << perms); Array<Array<int> > ccTerms; Array<Array<int> > cvTerms; Array<Array<int> > vcTerms; Array<Array<int> > vvTerms; Array<int> startingVector; ProductParity startingParity; bool hasStartingVector = false; for (ProductRulePerms::const_iterator iter = perms.begin(); iter != perms.end(); iter++) { Tabs tab1; MultipleDeriv dLeft = iter->first.first(); MultipleDeriv dRight = iter->first.second(); int multiplicity = iter->second; /* skip this combination if we've already pulled it out * for workspace */ if (hasVectorWorkspace && workspaceIsLeft && dLeft.order()==order) continue; if (hasVectorWorkspace && !workspaceIsLeft && dRight.order()==order) continue; if (!leftSparsity()->containsDeriv(dLeft) || !rightSparsity()->containsDeriv(dRight)) continue; int iLeft = leftSparsity()->getIndex(dLeft); int iRight = rightSparsity()->getIndex(dRight); if (iLeft==-1 || iRight==-1) continue; SUNDANCE_MSG4(verb, tab1 << "left deriv=" << dLeft); SUNDANCE_MSG4(verb, tab1 << "right deriv=" << dRight); bool leftIsConst = leftSparsity()->state(iLeft)==ConstantDeriv; bool rightIsConst = rightSparsity()->state(iRight)==ConstantDeriv; if (leftIsConst) { Tabs tab2; SUNDANCE_MSG4(verb, tab2 << "left is const"); int leftIndex = leftEval()->constantIndexMap().get(iLeft); if (rightIsConst) { SUNDANCE_MSG4(verb, tab2 << "right is const"); int rightIndex = rightEval()->constantIndexMap().get(iRight); ccTerms.append(tuple(leftIndex, rightIndex, multiplicity)); } else { SUNDANCE_MSG4(verb, tab2 << "right is vec"); int rightIndex = rightEval()->vectorIndexMap().get(iRight); if (!hasVectorWorkspace && !hasStartingVector) { SUNDANCE_MSG4(verb, tab1 << "found c-v starting vec"); startingVector = tuple(leftIndex, rightIndex, multiplicity); hasStartingVector = true; startingParity = ConstVec; } else { SUNDANCE_MSG4(verb, tab1 << "found c-v term"); cvTerms.append(tuple(leftIndex, rightIndex, multiplicity)); } } } else { Tabs tab2; SUNDANCE_MSG4(verb, tab2 << "left is vec"); int leftIndex = leftEval()->vectorIndexMap().get(iLeft); if (rightIsConst) { SUNDANCE_MSG4(verb, tab2 << "right is const"); int rightIndex = rightEval()->constantIndexMap().get(iRight); if (!hasVectorWorkspace && !hasStartingVector) { SUNDANCE_MSG4(verb, tab1 << "found v-c starting vec"); startingVector = tuple(leftIndex, rightIndex, multiplicity); hasStartingVector = true; startingParity = VecConst; } else { SUNDANCE_MSG4(verb, tab1 << "found v-c term"); vcTerms.append(tuple(leftIndex, rightIndex, multiplicity)); } } else { SUNDANCE_MSG4(verb, tab2 << "right is vec"); int rightIndex = rightEval()->vectorIndexMap().get(iRight); if (!hasVectorWorkspace && !hasStartingVector) { SUNDANCE_MSG4(verb, tab1 << "found v-v starting vec"); startingVector = tuple(leftIndex, rightIndex, multiplicity); hasStartingVector = true; startingParity = VecVec; } else { SUNDANCE_MSG4(verb, tab1 << "found v-v term"); vvTerms.append(tuple(leftIndex, rightIndex, multiplicity)); } } } } ccTerms_[order].append(ccTerms); cvTerms_[order].append(cvTerms); vcTerms_[order].append(vcTerms); vvTerms_[order].append(vvTerms); startingVectors_[order].append(startingVector); startingParities_[order].append(startingParity); if (verb > 2) { Tabs tab0; Out::os() << tab0 << "deriv " << i << " order=" << order ; if (resultIsConstant) { Out::os() << " constant result, index= "; } else { Out::os() << " vector result, index= "; } Out::os() << resultIndex_[order] << std::endl; { Tabs tab1; if (hasStartingVector) { Out::os() << tab1 << "starting vector " << startingVector << std::endl; } Out::os() << tab1 << "c-c terms " << ccTerms << std::endl; Out::os() << tab1 << "c-v terms " << cvTerms << std::endl; Out::os() << tab1 << "v-c terms " << vcTerms << std::endl; Out::os() << tab1 << "v-v terms " << vvTerms << std::endl; } } } if (verb > 2) { Out::os() << tabs << "maps: " << std::endl; Out::os() << tabs << "vector index map " << vectorIndexMap() << std::endl; Out::os() << tabs << "constant index map " << constantIndexMap() << std::endl; } } catch(std::exception& e) { TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "exception detected in ProductEvaluator: expr=" << expr->toString() << std::endl << "exception=" << e.what()); } }