Beispiel #1
0
/*!\brief Expand an expression of the form scale * addition
 *
 * Provided \c scale is not a sum, expand the expression
 * <tt>scale * (+ c a1 ...)</tt> into <tt>scale * c + scale * a1 + ...</tt>.
 */
ptr<const sum>
expand_prod_sum( const expr &scale, const sum  &addition )
{
  ASSERT( addition.is_expanded() && ! scale.is_a< sum >() );

  if( scale.is_numerical() )
  { // easy case -> sum::sca does the work
    const number &ns = scale.as_a< numerical >()->get();

    ptr< const sum > ret
      = ns.unit()
      ? &addition
      : sum::sca( ns, addition );

    ret->basic::expand();
    return ret;
  }

  // hard case : distribute term by term

  number coef = 0;

  ptr< const prod > scale_prod = scale.get()->as_prod();

  // addition.size() for nsp * addition
  // + 1 for scale_prod * addition.coef()
  container::ptr_unsafe_vector< const prod > seq ( addition.size() + 1 );

  { // coefficient handling
    const prod* ph = scale_prod.get();

    // cannot be numerical since [scale_prod] isn't
    seq.push_back( prod::handle::sca( ph, addition.coef() ) );
  }
  for(const prod* p : addition)
  {
    ASSERT( p );

    const expr ex = prod::mul( *p, *scale_prod );

    // seams reasonable here
    ASSERT( ! ex.is_a< sum >() );

    if( ex.is_numerical() )
      coef += ex.as_a< numerical >()->get();

    else
      seq.push_back( ex.get()->as_prod() );
  }

  expand_detail::sort( seq.begin(), seq.end() );

  ptr< const sum > ret = sum::from_sorted_prod_range( coef, seq.begin(), seq.end() );
  ret->basic::expand(); // mark expanded
  return ret;
}
Beispiel #2
0
bool basic::match(const expr &e, match_state &mm) const
{
  if( e.is_a< wildcard_ >() )
    return match_wild( *this, *e.as_a< wildcard_ >(), mm );

  if( RTTI_ID( this ) != RTTI_ID( e.get() ) )
    return false;

  return match_same_type( *e.get(), mm );
}
Beispiel #3
0
value expr_copy(const expr &e)
{
  value res = expr_allocate();
  Field( res, 1 ) = RTTI_ID( e.get() );
  expr_construct( res ) expr( e );
  return res;
}