Пример #1
0
bool Expr::tryMultiplyComplex(const Expr& L, const Expr& R,
  Expr& rtn) const
{
  TimeMonitor t(tryMultiplyComplexTimer());
  TEUCHOS_TEST_FOR_EXCEPTION(L.size() != 1 || R.size() != 1, std::logic_error, 
    "non-scalar exprs should have been reduced before "
    "call to tryMultiplyComplex(). Left=" << L << " right="
    << R);

  if (L.isComplex() || R.isComplex())
  {
    if (Re(L).sameAs(Re(R)) && Im(L).sameAs(-Im(R)))
    {
      rtn = Re(R)*Re(R) + Im(R)*Im(R);
    }
    else
    {
      Expr re = Re(L)*Re(R) - Im(L)*Im(R);
      Expr im = Re(L)*Im(R) + Im(L)*Re(R);
      rtn = new ComplexExpr(re, im);
    }
    return true;
  }
  else
  {
    return false;
  }
}
Пример #2
0
bool Expr::tryAddComplex(const Expr& L, const Expr& R, int sign,
  Expr& rtn) const
{
  TimeMonitor t(trySumComplexTimer());
  TEUCHOS_TEST_FOR_EXCEPTION(L.size() != 1 || R.size() != 1, std::logic_error, 
    "non-scalar exprs should have been reduced before "
    "call to tryAddComplex(). Left=" << L << " right="
    << R);
  if (L.isComplex() || R.isComplex())
  {
    if (sign > 0) 
    {
      rtn = new ComplexExpr(L.real() + R.real(), 
        L.imag() + R.imag());
    }
    else
    {
      rtn = new ComplexExpr(L.real() - R.real(), 
        L.imag() - R.imag());
    }
    return true;
  }
  else
  {
    return false;
  }
}
Пример #3
0
Expr Expr::operator/(const Expr& other) const 
{
  TimeMonitor t(opTimer());

  /* if the right operand is a list, this operation
   * makes no sense */
  TEUCHOS_TEST_FOR_EXCEPTION(other.size() != 1,
    std::runtime_error, 
    "Expr::operator/ detected division by a non-scalar "
    "expression " << toString());

  TEUCHOS_TEST_FOR_EXCEPTION(other.isSpectral(), std::logic_error, 
    "Division by a Spectral Expr is not yet defined");

  /* If other is complex, transform to make the denominator real */
  if (other.isComplex())
  {
    Expr magSq = other.real()*other.real() + other.imag()*other.imag();
    return (*this) * other.conj() / magSq;
  }

  /* If I'm complex and the other is not, distribute division over re and im */
  if (isComplex() && !other.isComplex())
  {
    return new ComplexExpr(real()/other, imag()/other);
  }

  /* If I'm spectral and the other is not, distribute division over coefficients */
  if (isSpectral() && !other.isSpectral()  && !other.isComplex())
  {
    const SpectralExpr* se 
      = dynamic_cast<const SpectralExpr*>((*this)[0].ptr().get());

    SpectralBasis basis = se->getSpectralBasis();
    Array<Expr> coeff(basis.nterms());
	  
    for(int i=0; i<basis.nterms(); i++)
    {
      coeff[i] = se->getCoeff(i)/ other[0];
    }
    Expr rtn = new SpectralExpr( basis, coeff);
    return rtn;
  }

  /* if we are a scalar, do simple scalar division */
  if (this->size()==1)
  {
    return (*this)[0].divide(other[0]);
  }

  /* otherwise, divide each element of the left by the right operand */
  Array<Expr> rtn(this->size());
  for (int i=0; i<this->size(); i++)
  {
    rtn[i] = (*this)[i] / other;
  }
  return new ListExpr(rtn);
}
Пример #4
0
Expr Complex(const Expr& re, const Expr& im)
{
  TEUCHOS_TEST_FOR_EXCEPTION(re.size() != im.size(), std::runtime_error,
    "arguments mismatched in Complex(). Real part="
    << re << ", imaginary part=" << im);

  TEUCHOS_TEST_FOR_EXCEPTION(re.isComplex() || im.isComplex(), std::runtime_error,
    "recursively defined complex number. Real part="
    << re << ", imaginary part=" << im);

  if (re.totalSize() > 1)
  {
    Array<Expr> rtn(re.size());
    for (int i=0; i<re.size(); i++)
    {
      rtn[i] = Complex(re[i], im[i]);
    }
    return new ListExpr(rtn);
  }

  const ZeroExpr* zr = dynamic_cast<const ZeroExpr*>(re[0].ptr().get());
  const ZeroExpr* zi = dynamic_cast<const ZeroExpr*>(im[0].ptr().get());

  if (zr == 0) /* nonzero real part */
  {
    if (zi==0) /* nonzero imag part */
    {
      return new ComplexExpr(re, im);
    }
    else /* zero imag part */
    {
      return re;
    }
  }
  else /* zero real part */
  {
    if (zi != 0) /* both are zero */
    {
      return Expr(0.0);
    }
    else /* pure imaginary */
    {
      return new ComplexExpr(0.0, im);
    }
  }
  return new ComplexExpr(re, im);
}