www.mooseframework.org
ExpressionBuilder.h
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #pragma once
11 
12 #include <vector>
13 #include <ostream>
14 #include <sstream>
15 #include <iomanip>
16 
17 #include "MooseError.h"
18 #include "libmesh/libmesh_common.h"
19 
20 using namespace libMesh;
21 
48 {
49 public:
51 
52  // forward delcarations
53  class EBTerm;
54  class EBTermNode;
55  class EBFunction;
57  typedef std::vector<EBTerm> EBTermList;
58  typedef std::vector<EBTermNode *> EBTermNodeList;
59  typedef std::vector<const EBSubstitutionRule *> EBSubstitutionRuleList;
60 
62  class EBTermNode
63  {
64  public:
65  virtual ~EBTermNode(){};
66  virtual EBTermNode * clone() const = 0;
67 
68  virtual std::string stringify() const = 0;
69  virtual unsigned int substitute(const EBSubstitutionRuleList & /*rule*/) { return 0; }
70  virtual int precedence() const = 0;
71  friend std::ostream & operator<<(std::ostream & os, const EBTermNode & node)
72  {
73  return os << node.stringify();
74  }
75  };
76 
78  template <typename T>
79  class EBNumberNode : public EBTermNode
80  {
81  T _value;
82 
83  public:
84  EBNumberNode(T value) : _value(value){};
85  virtual EBNumberNode<T> * clone() const { return new EBNumberNode(_value); }
86 
87  virtual std::string stringify() const;
88  virtual int precedence() const { return 0; }
89  };
90 
92  class EBSymbolNode : public EBTermNode
93  {
94  std::string _symbol;
95 
96  public:
97  EBSymbolNode(std::string symbol) : _symbol(symbol){};
98  virtual EBSymbolNode * clone() const { return new EBSymbolNode(_symbol); }
99 
100  virtual std::string stringify() const;
101  virtual int precedence() const { return 0; }
102  };
103 
108  class EBTempIDNode : public EBTermNode
109  {
110  unsigned long _id;
111 
112  public:
113  EBTempIDNode(unsigned int id) : _id(id){};
114  virtual EBTempIDNode * clone() const { return new EBTempIDNode(_id); }
115 
116  virtual std::string stringify() const; // returns "[idnumber]"
117  virtual int precedence() const { return 0; }
118  };
119 
122  {
123  public:
124  EBUnaryTermNode(EBTermNode * subnode) : _subnode(subnode){};
125  virtual ~EBUnaryTermNode() { delete _subnode; };
126 
127  virtual unsigned int substitute(const EBSubstitutionRuleList & rule);
128  const EBTermNode * getSubnode() const { return _subnode; }
129 
130  protected:
132  };
133 
136  {
137  public:
138  enum NodeType
139  {
149  COSH
150  } _type;
151 
153  : EBUnaryTermNode(subnode), _type(type){};
154  virtual EBUnaryFuncTermNode * clone() const
155  {
156  return new EBUnaryFuncTermNode(_subnode->clone(), _type);
157  };
158 
159  virtual std::string stringify() const;
160  virtual int precedence() const { return 2; }
161  };
162 
165  {
166  public:
167  enum NodeType
168  {
170  LOGICNOT
171  } _type;
172 
174  : EBUnaryTermNode(subnode), _type(type){};
175  virtual EBUnaryOpTermNode * clone() const
176  {
177  return new EBUnaryOpTermNode(_subnode->clone(), _type);
178  };
179 
180  virtual std::string stringify() const;
181  virtual int precedence() const { return 3; }
182  };
183 
186  {
187  public:
188  EBBinaryTermNode(EBTermNode * left, EBTermNode * right) : _left(left), _right(right){};
190  {
191  delete _left;
192  delete _right;
193  };
194 
195  virtual unsigned int substitute(const EBSubstitutionRuleList & rule);
196 
197  protected:
200  };
201 
204  {
205  public:
206  enum NodeType
207  {
218  EQ,
219  NOTEQ
220  };
221 
223  : EBBinaryTermNode(left, right), _type(type){};
224  virtual EBBinaryOpTermNode * clone() const
225  {
226  return new EBBinaryOpTermNode(_left->clone(), _right->clone(), _type);
227  };
228 
229  virtual std::string stringify() const;
230  virtual int precedence() const;
231 
232  protected:
234  };
235 
238  {
239  public:
240  enum NodeType
241  {
246  PLOG
247  } _type;
248 
250  : EBBinaryTermNode(left, right), _type(type){};
251  virtual EBBinaryFuncTermNode * clone() const
252  {
253  return new EBBinaryFuncTermNode(_left->clone(), _right->clone(), _type);
254  };
255 
256  virtual std::string stringify() const;
257  virtual int precedence() const { return 2; }
258  };
259 
262  {
263  public:
265  : EBBinaryTermNode(left, right), _middle(middle){};
266  virtual ~EBTernaryTermNode() { delete _middle; };
267 
268  virtual unsigned int substitute(const EBSubstitutionRuleList & rule);
269 
270  protected:
272  };
273 
276  {
277  public:
278  enum NodeType
279  {
280  CONDITIONAL
281  } _type;
282 
284  : EBTernaryTermNode(left, middle, right), _type(type){};
285  virtual EBTernaryFuncTermNode * clone() const
286  {
287  return new EBTernaryFuncTermNode(_left->clone(), _middle->clone(), _right->clone(), _type);
288  };
289 
290  virtual std::string stringify() const;
291  virtual int precedence() const { return 2; }
292  };
293 
298  {
299  public:
300  virtual EBTermNode * apply(const EBTermNode *) const = 0;
301  virtual ~EBSubstitutionRule() {}
302  };
303 
307  template <class Node_T>
309  {
310  public:
311  virtual EBTermNode * apply(const EBTermNode *) const;
312 
313  protected:
314  // on successful substitution this returns a new node to replace the old one, otherwise it
315  // returns NULL
316  virtual EBTermNode * substitute(const Node_T &) const = 0;
317  };
318 
323  class EBTermSubstitution : public EBSubstitutionRuleTyped<EBSymbolNode>
324  {
325  public:
326  EBTermSubstitution(const EBTerm & find, const EBTerm & replace);
327  virtual ~EBTermSubstitution() { delete _replace; }
328  protected:
329  virtual EBTermNode * substitute(const EBSymbolNode &) const;
330  std::string _find;
332  };
333 
338  class EBLogPlogSubstitution : public EBSubstitutionRuleTyped<EBUnaryFuncTermNode>
339  {
340  public:
341  EBLogPlogSubstitution(const EBTerm & epsilon) : _epsilon(epsilon.cloneRoot())
342  {
343  mooseAssert(_epsilon != NULL, "Epsilon must not be an empty term in EBLogPlogSubstitution");
344  }
345  virtual ~EBLogPlogSubstitution() { delete _epsilon; }
346  protected:
347  virtual EBTermNode * substitute(const EBUnaryFuncTermNode &) const;
349  };
350 
357  class EBTerm
358  {
359  public:
360  // the default constructor assigns a temporary id node to root we use the address of the
361  // current EBTerm object as the ID. This could be problematic if we create and destroy terms,
362  // but then we should not expect the substitution to do sane things anyways.
363  EBTerm() : _root(new EBTempIDNode(reinterpret_cast<unsigned long>(this))){};
364 
365  EBTerm(const EBTerm & term) : _root(term.cloneRoot()){};
366  ~EBTerm() { delete _root; };
367 
368  private:
369  // construct a term from a node
370  EBTerm(EBTermNode * root) : _root(root){};
371 
372  public:
373  // construct from number or string
374  EBTerm(int number) : _root(new EBNumberNode<int>(number)) {}
375  EBTerm(Real number) : _root(new EBNumberNode<Real>(number)) {}
376  EBTerm(const char * symbol) : _root(new EBSymbolNode(symbol)) {}
377 
378  // concatenate terms to form a parameter list with (()) syntax (those need to be out-of-class!)
379  friend EBTermList operator,(const ExpressionBuilder::EBTerm & larg,
380  const ExpressionBuilder::EBTerm & rarg);
381  friend EBTermList operator,(const ExpressionBuilder::EBTerm & larg,
382  const ExpressionBuilder::EBTermList & rargs);
384  const ExpressionBuilder::EBTerm & rarg);
385 
386  // dump term as FParser expression
387  friend std::ostream & operator<<(std::ostream & os, const EBTerm & term);
388  // cast into a string
389  operator std::string() const { return _root->stringify(); }
390 
391  // assign a term
392  EBTerm & operator=(const EBTerm & term)
393  {
394  delete _root;
395  _root = term.cloneRoot();
396  return *this;
397  }
398 
399  // perform a substitution (returns substituton count)
400  unsigned int substitute(const EBSubstitutionRule & rule);
401  unsigned int substitute(const EBSubstitutionRuleList & rules);
402 
403  const EBTermNode * getRoot() const { return _root; }
404  EBTermNode * cloneRoot() const { return _root == NULL ? NULL : _root->clone(); }
405 
406  protected:
408 
409  public:
413 #define UNARY_OP_IMPLEMENT(op, OP) \
414  EBTerm operator op() const \
415  { \
416  mooseAssert(_root != NULL, "Empty term provided for unary operator " #op); \
417  return EBTerm(new EBUnaryOpTermNode(cloneRoot(), EBUnaryOpTermNode::OP)); \
418  }
419  UNARY_OP_IMPLEMENT(-, NEG)
420  UNARY_OP_IMPLEMENT(!, LOGICNOT)
421 
422 
425  friend EBTerm sin(const EBTerm &);
426  friend EBTerm cos(const EBTerm &);
427  friend EBTerm tan(const EBTerm &);
428  friend EBTerm abs(const EBTerm &);
429  friend EBTerm log(const EBTerm &);
430  friend EBTerm log2(const EBTerm &);
431  friend EBTerm log10(const EBTerm &);
432  friend EBTerm exp(const EBTerm &);
433  friend EBTerm sinh(const EBTerm &);
434  friend EBTerm cosh(const EBTerm &);
435 
436 /*
437  * Binary operators (including number,term operations)
438  */
439 #define BINARY_OP_IMPLEMENT(op, OP) \
440  EBTerm operator op(const EBTerm & term) const \
441  { \
442  mooseAssert(_root != NULL, "Empty term provided on left side of operator " #op); \
443  mooseAssert(term._root != NULL, "Empty term provided on right side of operator " #op); \
444  return EBTerm(new EBBinaryOpTermNode(cloneRoot(), term.cloneRoot(), EBBinaryOpTermNode::OP)); \
445  } \
446  friend EBTerm operator op(int left, const EBTerm & right) \
447  { \
448  mooseAssert(right._root != NULL, "Empty term provided on right side of operator " #op); \
449  return EBTerm(new EBBinaryOpTermNode( \
450  new EBNumberNode<int>(left), right.cloneRoot(), EBBinaryOpTermNode::OP)); \
451  } \
452  friend EBTerm operator op(Real left, const EBTerm & right) \
453  { \
454  mooseAssert(right._root != NULL, "Empty term provided on right side of operator " #op); \
455  return EBTerm(new EBBinaryOpTermNode( \
456  new EBNumberNode<Real>(left), right.cloneRoot(), EBBinaryOpTermNode::OP)); \
457  } \
458  friend EBTerm operator op(const EBFunction & left, const EBTerm & right) \
459  { \
460  mooseAssert(EBTerm(left)._root != NULL, "Empty term provided on left side of operator " #op); \
461  mooseAssert(right._root != NULL, "Empty term provided on right side of operator " #op); \
462  return EBTerm(new EBBinaryOpTermNode( \
463  EBTerm(left).cloneRoot(), right.cloneRoot(), EBBinaryOpTermNode::OP)); \
464  } \
465  friend EBTerm operator op(const EBFunction & left, const EBFunction & right); \
466  friend EBTerm operator op(int left, const EBFunction & right); \
467  friend EBTerm operator op(Real left, const EBFunction & right);
468  BINARY_OP_IMPLEMENT(+, ADD)
469  BINARY_OP_IMPLEMENT(-, SUB)
470  BINARY_OP_IMPLEMENT(*, MUL)
471  BINARY_OP_IMPLEMENT(/, DIV)
472  BINARY_OP_IMPLEMENT(%, MOD)
473  BINARY_OP_IMPLEMENT(<, LESS)
474  BINARY_OP_IMPLEMENT(>, GREATER)
475  BINARY_OP_IMPLEMENT(<=, LESSEQ)
476  BINARY_OP_IMPLEMENT(>=, GREATEREQ)
477  BINARY_OP_IMPLEMENT(==, EQ)
478  BINARY_OP_IMPLEMENT(!=, NOTEQ)
479 
480 /*
481  * Compound assignment operators
482  */
483 #define BINARYCOMP_OP_IMPLEMENT(op, OP) \
484  EBTerm & operator op(const EBTerm & term) \
485  { \
486  mooseAssert(_root != NULL, "Empty term provided on left side of operator " #op); \
487  mooseAssert(term._root != NULL, "Empty term provided on right side of operator " #op); \
488  if (dynamic_cast<EBTempIDNode *>(_root)) \
489  mooseError("Using compound assignment operator on anonymous term. Set it to 0 first!"); \
490  _root = new EBBinaryOpTermNode(_root, term.cloneRoot(), EBBinaryOpTermNode::OP); \
491  return *this; \
492  }
493  BINARYCOMP_OP_IMPLEMENT(+=, ADD)
494  BINARYCOMP_OP_IMPLEMENT(-=, SUB)
495  BINARYCOMP_OP_IMPLEMENT(*=, MUL)
496  BINARYCOMP_OP_IMPLEMENT(/=, DIV)
497  BINARYCOMP_OP_IMPLEMENT(%=, MOD)
498 
499 
503  friend EBTerm min(const EBTerm &, const EBTerm &);
504  friend EBTerm max(const EBTerm &, const EBTerm &);
505  friend EBTerm pow(const EBTerm &, const EBTerm &);
506  template <typename T>
507  friend EBTerm pow(const EBTerm &, T exponent);
508  friend EBTerm atan2(const EBTerm &, const EBTerm &);
509  friend EBTerm hypot(const EBTerm &, const EBTerm &);
510  friend EBTerm plog(const EBTerm &, const EBTerm &);
512 
516  friend EBTerm conditional(const EBTerm &, const EBTerm &, const EBTerm &);
517  };
518 
521  {
522  public:
524 
528  EBFunction & operator()(const EBTerm & arg);
529  EBFunction & operator()(const EBTermList & args);
531 
534  EBFunction & operator()(const EBTerm & a1, const EBTerm & a2) { return (*this)((a1, a2)); }
535  EBFunction & operator()(const EBTerm & a1, const EBTerm & a2, const EBTerm & a3)
536  {
537  return (*this)((a1, a2, a3));
538  }
539  EBFunction &
540  operator()(const EBTerm & a1, const EBTerm & a2, const EBTerm & a3, const EBTerm & a4)
541  {
542  return (*this)((a1, a2, a3, a4));
543  }
545  const EBTerm & a2,
546  const EBTerm & a3,
547  const EBTerm & a4,
548  const EBTerm & a5)
549  {
550  return (*this)((a1, a2, a3, a4, a5));
551  }
553  const EBTerm & a2,
554  const EBTerm & a3,
555  const EBTerm & a4,
556  const EBTerm & a5,
557  const EBTerm & a6)
558  {
559  return (*this)((a1, a2, a3, a4, a5, a6));
560  }
562  const EBTerm & a2,
563  const EBTerm & a3,
564  const EBTerm & a4,
565  const EBTerm & a5,
566  const EBTerm & a6,
567  const EBTerm & a7)
568  {
569  return (*this)((a1, a2, a3, a4, a5, a6, a7));
570  }
572  const EBTerm & a2,
573  const EBTerm & a3,
574  const EBTerm & a4,
575  const EBTerm & a5,
576  const EBTerm & a6,
577  const EBTerm & a7,
578  const EBTerm & a8)
579  {
580  return (*this)((a1, a2, a3, a4, a5, a6, a7, a8));
581  }
583  const EBTerm & a2,
584  const EBTerm & a3,
585  const EBTerm & a4,
586  const EBTerm & a5,
587  const EBTerm & a6,
588  const EBTerm & a7,
589  const EBTerm & a8,
590  const EBTerm & a9)
591  {
592  return (*this)((a1, a2, a3, a4, a5, a6, a7, a8, a9));
593  }
595 
597  operator EBTerm() const;
598 
600  operator std::string() const;
601 
604  EBFunction & operator=(const EBTerm &);
605  EBFunction & operator=(const EBFunction &);
607 
609  std::string args();
610 
613  EBTerm operator-() { return -EBTerm(*this); }
614  EBTerm operator!() { return !EBTerm(*this); }
616 
617  // perform a substitution (returns substituton count)
618  unsigned int substitute(const EBSubstitutionRule & rule);
619  unsigned int substitute(const EBSubstitutionRuleList & rules);
620 
621  protected:
626 
627  // underlying term that the _eval_arguments are substituted in
629  };
630 
631 /*
632  * Binary operators
633  */
634 #define BINARYFUNC_OP_IMPLEMENT(op, OP) \
635  friend EBTerm operator op(const EBFunction & left, const EBFunction & right) \
636  { \
637  mooseAssert(EBTerm(left)._root != NULL, "Empty term provided on left side of operator " #op); \
638  mooseAssert(EBTerm(right)._root != NULL, \
639  "Empty term provided on right side of operator " #op); \
640  return EBTerm(new EBBinaryOpTermNode( \
641  EBTerm(left).cloneRoot(), EBTerm(right).cloneRoot(), EBBinaryOpTermNode::OP)); \
642  } \
643  friend EBTerm operator op(int left, const EBFunction & right) \
644  { \
645  mooseAssert(EBTerm(right)._root != NULL, \
646  "Empty term provided on right side of operator " #op); \
647  return EBTerm(new EBBinaryOpTermNode( \
648  new EBNumberNode<int>(left), EBTerm(right).cloneRoot(), EBBinaryOpTermNode::OP)); \
649  } \
650  friend EBTerm operator op(Real left, const EBFunction & right) \
651  { \
652  mooseAssert(EBTerm(right)._root != NULL, \
653  "Empty term provided on right side of operator " #op); \
654  return EBTerm(new EBBinaryOpTermNode( \
655  new EBNumberNode<Real>(left), EBTerm(right).cloneRoot(), EBBinaryOpTermNode::OP)); \
656  }
657  BINARYFUNC_OP_IMPLEMENT(+, ADD)
658  BINARYFUNC_OP_IMPLEMENT(-, SUB)
659  BINARYFUNC_OP_IMPLEMENT(*, MUL)
660  BINARYFUNC_OP_IMPLEMENT(/, DIV)
661  BINARYFUNC_OP_IMPLEMENT(%, MOD)
662  BINARYFUNC_OP_IMPLEMENT(<, LESS)
663  BINARYFUNC_OP_IMPLEMENT(>, GREATER)
664  BINARYFUNC_OP_IMPLEMENT(<=, LESSEQ)
665  BINARYFUNC_OP_IMPLEMENT(>=, GREATEREQ)
666  BINARYFUNC_OP_IMPLEMENT(==, EQ)
667  BINARYFUNC_OP_IMPLEMENT(!=, NOTEQ)
668 };
669 
670 // convenience function for numeric exponent
671 template <typename T>
673 pow(const ExpressionBuilder::EBTerm & left, T exponent)
674 {
679 }
680 
681 // convert a number node into a string
682 template <typename T>
683 std::string
685 {
686  std::ostringstream s;
687  s << std::setprecision(12) << _value;
688  return s.str();
689 }
690 
691 template <class Node_T>
694  const ExpressionBuilder::EBTermNode * node) const
695 {
696  const Node_T * match_node = dynamic_cast<const Node_T *>(node);
697  if (match_node == NULL)
698  return NULL;
699  else
700  return substitute(*match_node);
701 }
702 
Node representing a function with three arguments.
User facing host object for an expression tree.
virtual EBNumberNode< T > * clone() const
Base class for nodes with two sub nodes (i.e. functions or operators taking two arguments) ...
virtual EBUnaryOpTermNode * clone() const
virtual EBBinaryOpTermNode * clone() const
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3, const EBTerm &a4, const EBTerm &a5, const EBTerm &a6)
Node representing a unary operator.
std::ostream & operator<<(std::ostream &stream, const MutableCoefficientsInterface &me)
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3, const EBTerm &a4)
Template class for leaf nodes holding anonymous IDs in the expression tree.
Node representing a binary operator.
ExpressionBuilder::EBTermList operator,(const ExpressionBuilder::EBTerm &larg, const ExpressionBuilder::EBTerm &rarg)
Base class for nodes with a single sub node (i.e. functions or operators taking one argument) ...
virtual EBUnaryFuncTermNode * clone() const
const EBTermNode * getSubnode() const
EBTermList _eval_arguments
argument list passed in when evaluating the function
Node representing a function with two arguments.
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3, const EBTerm &a4, const EBTerm &a5, const EBTerm &a6, const EBTerm &a7, const EBTerm &a8, const EBTerm &a9)
virtual EBTermNode * clone() const =0
std::vector< EBTerm > EBTermList
ExpressionBuilder adds an interface to derived classes that enables convenient construction of FParse...
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3)
virtual std::string stringify() const
virtual EBSymbolNode * clone() const
Substitution rule base class that applies to nodes of type Node_T.
EBBinaryTermNode(EBTermNode *left, EBTermNode *right)
Base class for nodes in the expression tree.
virtual EBTempIDNode * clone() const
friend std::ostream & operator<<(std::ostream &os, const EBTermNode &node)
Template class for leaf nodes holding symbols (i.e. variables) in the expression tree.
Template class for leaf nodes holding numbers in the expression tree.
virtual unsigned int substitute(const EBSubstitutionRuleList &)
Node representing a function with two arguments.
EBUnaryOpTermNode(EBTermNode *subnode, NodeType type)
EBUnaryFuncTermNode(EBTermNode *subnode, NodeType type)
Real root(std::function< Real(Real)> const &f, Real x1, Real x2, Real tol=1.0e-12)
Finds the root of a function using Brent&#39;s method.
Definition: BrentsMethod.C:61
virtual EBBinaryFuncTermNode * clone() const
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2)
virtual std::string stringify() const =0
std::vector< const EBSubstitutionRule * > EBSubstitutionRuleList
virtual EBTernaryFuncTermNode * clone() const
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
const EBTermNode * getRoot() const
Substitution rule to replace all occurences of log(x) with plog(x, epsilon) with a user defined term ...
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3, const EBTerm &a4, const EBTerm &a5, const EBTerm &a6, const EBTerm &a7, const EBTerm &a8)
std::vector< EBTermNode * > EBTermNodeList
User facing host object for a function. This combines a term with an argument list.
EBTerm(const char *symbol)
EBTernaryFuncTermNode(EBTermNode *left, EBTermNode *middle, EBTermNode *right, NodeType type)
EBTermList _arguments
argument list the function is declared with
EBTernaryTermNode(EBTermNode *left, EBTermNode *middle, EBTermNode *right)
virtual EBTermNode * apply(const EBTermNode *) const
Generic Substitution rule to replace all occurences of a given symbol node term with a user defined t...
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3, const EBTerm &a4, const EBTerm &a5)
EBTerm(const EBTerm &term)
Substitution rule functor base class to perform flexible term substitutions.
EBBinaryFuncTermNode(EBTermNode *left, EBTermNode *right, NodeType type)
EBFunction & operator()(const EBTerm &a1, const EBTerm &a2, const EBTerm &a3, const EBTerm &a4, const EBTerm &a5, const EBTerm &a6, const EBTerm &a7)
EBTermNode * cloneRoot() const
EBBinaryOpTermNode(EBTermNode *left, EBTermNode *right, NodeType type)
Base class for nodes with two sub nodes (i.e. functions or operators taking two arguments) ...
EBTerm & operator=(const EBTerm &term)