TEST_F(TestGFM,PositiveNegative)
{
    alps::gf::momentum_index i; i=2;
    alps::gf::momentum_index j=alps::gf::momentum_index(3);
    alps::gf::index sigma(1);

    matsubara_indexp_type omega; omega=4;
    
    gf1(omega, i,j,sigma)=std::complex<double>(3,4);
    std::complex<double> x=gf1(omega,i,j,sigma);

    EXPECT_EQ(3,x.real());
    EXPECT_EQ(4,x.imag());

    matsubara_indexn_type omega2; omega2=-4;
    gf2(omega2, i,j,sigma)=std::complex<double>(3,4);
    x=gf2(omega2,i,j,sigma);

    EXPECT_EQ(3,x.real());
    EXPECT_EQ(4,x.imag());
}
TEST_F(TwoIndexGFTest,saveload)
{
    namespace g=alps::gf;
    {
        alps::hdf5::archive oar("gf.h5","w");
        gf(g::matsubara_index(4), g::index(1))=std::complex<double>(7., 3.);
        gf.save(oar,"/gf");
    }
    {
        alps::hdf5::archive iar("gf.h5");
        gf2.load(iar,"/gf");
    }
    EXPECT_EQ(7, gf2(g::matsubara_index(4), g::index(1)).real());
    EXPECT_EQ(3, gf2(g::matsubara_index(4), g::index(1)).imag());
    {
        alps::hdf5::archive oar("gf.h5","rw");
        oar["/gf/version/major"]<<7;
        EXPECT_THROW(gf2.load(oar,"/gf"),std::runtime_error);
    }
    EXPECT_EQ(7, gf2(g::matsubara_index(4), g::index(1)).real());
    EXPECT_EQ(3, gf2(g::matsubara_index(4), g::index(1)).imag());
}
TEST_F(TwoIndexGFTest,Assign)
{
    namespace g=alps::gf;
    g::omega_sigma_gf other_gf(matsubara_mesh(beta, nfreq*2), g::index_mesh(nspins));
    const g::matsubara_index omega(4);
    const g::index sigma(0);
    const std::complex<double> data(3,4);
    gf(omega,sigma)=data;
    
    gf2=gf;
    EXPECT_EQ(data, gf2(omega,sigma));
    EXPECT_THROW(other_gf=gf, std::invalid_argument);
    // EXPECT_EQ(data, other_gf(omega,sigma));
}
TEST_F(TwoIndexGFTest,printindexmesh)
{
  std::stringstream gf_stream;
  int nao=6;
  alps::gf::index_mesh mesh(nao);
  alps::gf::two_index_gf<double, alps::gf::index_mesh,alps::gf::index_mesh> gf2(mesh,mesh);
  gf2.initialize();
  gf_stream<<gf2;

  std::stringstream gf_stream_by_hand;
  gf_stream_by_hand<<alps::gf::index_mesh(nao)<<alps::gf::index_mesh(nao);
  for(int i=0;i<nao;++i){
    gf_stream_by_hand<<i<<" ";
    for(int j=0;j<nao;++j){
      gf_stream_by_hand<<"0 ";
    }
    gf_stream_by_hand<<std::endl;
  }
  EXPECT_EQ(gf_stream_by_hand.str(), gf_stream.str());
}
TEST_F(ThreeIndexTestGF,Operators)
{
    namespace g=alps::gf;

    for (g::matsubara_index om=g::matsubara_index(0); om<gf.mesh1().extent(); ++om) {
        for (g::momentum_index ii=g::momentum_index(0); ii<gf.mesh2().extent(); ++ii) {
            for (g::index sig=g::index(0); sig<gf.mesh3().extent(); ++sig) {
                std::complex<double> v1(1+om()+ii(), 1+sig());
                std::complex<double> v2=1./v1;
                gf(om,ii,sig)=v1;
                gf2(om,ii,sig)=v2;
            }
        }
    }


    gf_type g_plus=gf+gf2;
    gf_type g_minus=gf-gf2;

    const double tol=1E-8;
                    
    for (g::matsubara_index om=g::matsubara_index(0); om<gf.mesh1().extent(); ++om) {
        for (g::momentum_index ii=g::momentum_index(0); ii<gf.mesh2().extent(); ++ii) {
            for (g::index sig=g::index(0); sig<gf.mesh3().extent(); ++sig) {

                std::complex<double> v1(1+om()+ii(), 1+sig());
                std::complex<double> v2=1./v1;
                
                std::complex<double> r1=v1+v2;
                std::complex<double> r2=v1-v2;
                
                ASSERT_NEAR(r1.real(),g_plus(om,ii,sig).real(),tol);
                ASSERT_NEAR(r1.imag(),g_plus(om,ii,sig).imag(),tol);

                ASSERT_NEAR(r2.real(),g_minus(om,ii,sig).real(),tol);
                ASSERT_NEAR(r2.imag(),g_minus(om,ii,sig).imag(),tol);
            }
        }
    }
}