Expr SpectralPreprocessor::projectSpectral(
  const Array<Array<Expr> >& terms)
{
  Expr rtn = 0.0;
  
  for (int t=0; t<terms.size(); t++)
  {
    Expr test;
    Expr deterministic;
    Array<Expr> specs;
    Array<Expr> testCoeffs;
    Array<Array<Expr> > specCoeffs;
    Array<SpectralBasis> specBas;

    parseProduct(terms[t], test, deterministic, specs);
    
    const SpectralExpr* specTest 
      = dynamic_cast<const SpectralExpr*>(test.ptr().get());
    TEUCHOS_TEST_FOR_EXCEPT(specTest==0);

    SpectralBasis testBasis = specTest->getSpectralBasis();
    for (int i=0; i<testBasis.nterms(); i++)
    {
      testCoeffs.append(specTest->getCoeff(i));
    } 

    for (int i=0; i<specs.size(); i++)
    {
      const SpectralExpr* s 
        = dynamic_cast<const SpectralExpr*>(specs[i].ptr().get());
      SpectralBasis bas = s->getSpectralBasis();
      specBas.append(bas);
      Array<Expr> c;
      for (int j=0; j<bas.nterms(); j++)
      {
        c.append(s->getCoeff(j));
      }
      specCoeffs.append(c);
    }

    if (specs.size()==0)
    {
      for (int i=0; i<testBasis.nterms(); i++)
      {
        rtn = rtn + testCoeffs[i]*deterministic;
      } 
    }
    else if (specs.size()==1)
    {
      for (int i=0; i<testBasis.nterms(); i++)
      {
        rtn = rtn + testCoeffs[i]*specCoeffs[0][i]*deterministic;
      } 
    }
    else if (specs.size()==2U)
    {
      for (int i=0; i<testBasis.nterms(); i++)
      {
        for (int j=0; j<specBas[0].nterms(); j++)
        {
          for (int k=0; k<specBas[1].nterms(); k++)
          {
            double w = testBasis.expectation(
              specBas[0].getElement(j), specBas[1].getElement(k), i) 
              / testBasis.expectation(0,i,i);
            if (w==0.0) continue;
            rtn = rtn + w*testCoeffs[i]
              *specCoeffs[0][j]*specCoeffs[1][k]*deterministic;
          }
        }
      } 
    }
    else
    {
      TEUCHOS_TEST_FOR_EXCEPTION(specs.size() > 2, std::runtime_error,
        "not ready to work with more than two spectral unks");
    }
  }

  return rtn;
}