// @HEADER
//                           Intrepid2 Package
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Questions? Contact Kyungjoo Kim  (example@nnthink.com), or
//                    Mauro Perego  (example@nnthink.com)
// @HEADER

/** \file
\brief  Unit test (CubatureDirect): correctness of
        integration of monomials for 1D reference cells.
\author Created by P. Bochev and D. Ridzal.
*/

#include "Intrepid2_CubatureTensorSorted.hpp"
#include "Intrepid2_Utils.hpp"
#include "Teuchos_oblackholestream.hpp"
#include "Teuchos_RCP.hpp"
#include "Teuchos_GlobalMPISession.hpp"

using namespace Intrepid2;

/*
  Computes integrals of monomials over a given reference cell.
*/
long double evalQuad(std::vector<int> power, int dimension,
		     std::vector<int> order,
		     std::vector<EIntrepidBurkardt> rule) {

  CubatureTensorSorted<long double> lineCub(dimension,order,rule,false);
  order[0]--; order[1]--;
  CubatureTensorSorted<long double> lineCub1(dimension,order,rule,false);
  lineCub.update(1.0,lineCub1,1.0);

  int size = lineCub.getNumPoints();
  FieldContainer<long double> cubPoints(size,dimension);
  FieldContainer<long double> cubWeights(size);
  lineCub.getCubature(cubPoints,cubWeights);

  int mid  = size/2;
  long double Q = 0.0;
  if (size%2) {
    Q  = cubWeights(mid);
    for (int i=0; i<dimension; i++) {
      Q *= powl(cubPoints(mid,i),(long double)power[i]);
    }
  }

  for (int i=0; i<mid; i++) {
    long double value1 = cubWeights(i);
    long double value2 = cubWeights(size-i-1);
    for (int j=0; j<dimension; j++) {
      value1 *= powl(cubPoints(i,j),(long double)power[j]);
      value2 *= powl(cubPoints(size-i-1,j),(long double)power[j]);
    }
    Q += value1+value2;
  }
  return Q;
}

long double evalInt(int dimension, std::vector<int> power,
		    std::vector<EIntrepidBurkardt> rule)

  for (int i=0; i<dimension; i++) {
    if (rule[i]==BURK_CLENSHAWCURTIS||rule[i]==BURK_FEJER2||
	rule[i]==BURK_LEGENDRE||rule[i]==BURK_PATTERSON ||
	rule[i]==BURK_TRAPEZOIDAL) {
      if (power[i]%2)
	I *= 0.0;
      else
	I *= 2.0/((long double)power[i]+1.0);
    }
    else if (rule[i]==BURK_LAGUERRE) {
      I *= tgammal((long double)(power[i]+1));
    }
    else if (rule[i]==BURK_CHEBYSHEV1) {
      long double bot, top;
      if (!(power[i]%2)) {
	top = 1; bot = 1;
	for (int j=2;j<=power[i];j+=2) {
	  top *= (long double)(j-1);
	  bot *= (long double)j;
	}
	I *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_CHEBYSHEV2) {
      long double bot, top;
      if (!(power[i]%2)) {
      top = 1; bot = 1;
      for (int j=2;j<=power[i];j+=2) {
	top *= (long double)(j-1);
	bot *= (long double)j;
      }
      bot *= (long double)(power[i]+2);
      I   *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_HERMITE||rule[i]==BURK_GENZKEISTER) {
      if (power[i]%2) {
	I *= 0.0;
      }
      else {
	long double value = 1.0;
	if ((power[i]-1)>=1) {
	  int n_copy = power[i]-1;
	  while (1<n_copy) {
	    value  *= (long double)n_copy;
	    n_copy -= 2;
	  }
	}
	I *= value*sqrt(M_PI)/powl(2.0,(long double)power[i]/2.0);
      }
    }
  }
  return I;
}

int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);

  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  *outStream \
  << "===============================================================================\n" \
  << "|                                                                             |\n" \
  << "|                         Unit Test (CubatureTensorSorted)                    |\n" \
  << "|                                                                             |\n" \
  << "|     1) Computing integrals of monomials in 2D                               |\n" \
  << "|                                                                             |\n" \
  << "|  Questions? Contact  Drew Kouri (example@nnthink.com) or                     |\n" \
  << "|                      Denis Ridzal (example@nnthink.com).                     |\n" \
  << "|                                                                             |\n" \
  << "|  Intrepid's website: http://example.com           |\n" \
  << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
  << "|                                                                             |\n" \
  << "===============================================================================\n"\
  << "| TEST 12: integrals of monomials in 2D - Anisotropic but no growth rules     |\n"\
  << "===============================================================================\n";

  int dimension           = 2;
  int         errorFlag   = 0;
  long double reltol      = 1.0e+02*INTREPID_TOL;
  int         maxDeg      = 0;
  long double analyticInt = 0;
  long double testInt     = 0;
  int         maxOrder    = 20;
  std::vector<int> power(2,0);
  std::vector<EIntrepidBurkardt> rule1(2,BURK_CLENSHAWCURTIS);
  std::vector<int> order(2,0);

  *outStream << "\nIntegrals of monomials on a reference line (edge):\n";
  // compute and compare integrals
  try {
    for (int i=0; i<=maxOrder; i++) {
      maxDeg = i-2;

      order[0] = i; order[1] = i;
      for (int j=0; j <= maxDeg; j++) {
	power[0] = j;
	for (int k=0; k <= maxDeg; k++) {
	  power[1] = k;
	  analyticInt = 2.0*evalInt(dimension, power, rule1);
	  testInt     = evalQuad(power,dimension,order,rule1);

	  long double abstol  = (analyticInt == 0.0 ? reltol : std::fabs(reltol*analyticInt) );
	  long double absdiff = std::fabs(analyticInt - testInt);
	  *outStream << "Cubature order " << std::setw(2) << std::left << i
		     << " integrating "
		     << "x^" << std::setw(2) << std::left << j << "y^"
		     << std::setw(2) << std::left
		     << k <<  ":" << "   " << std::scientific
		     << std::setprecision(16) << testInt
		     << "   " << analyticInt << "   " << std::setprecision(4)
		     << absdiff << "   "
		     << "<?" << "   " << abstol << "\n";
	  if (absdiff > abstol) {
	    errorFlag++;
	    *outStream << std::right << std::setw(104) << "^^^^---FAILURE!\n";
	  }
	} // end for k
	*outStream << "\n";
      } // end for j
      *outStream << "\n";
    } // end for i
  }
  catch (std::logic_error &err) {
    *outStream << err.what() << "\n";
    errorFlag = -1;
  };

  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
Kokkos::finalize();
  return errorFlag;
}


for (int i=0; i<dimension; i++) {
    if (rule[i]==BURK_CLENSHAWCURTIS||rule[i]==BURK_FEJER2||
	rule[i]==BURK_LEGENDRE||rule[i]==BURK_PATTERSON ||
	rule[i]==BURK_TRAPEZOIDAL) {
      if (power[i]%2)
	I *= 0.0;
      else
	I *= 2.0/((long double)power[i]+1.0);
    }
    else if (rule[i]==BURK_LAGUERRE) {
      I *= tgammal((long double)(power[i]+1));
    }
    else if (rule[i]==BURK_CHEBYSHEV1) {
      long double bot, top;
      if (!(power[i]%2)) {
	top = 1; bot = 1;
	for (int j=2;j<=power[i];j+=2) {
	  top *= (long double)(j-1);
	  bot *= (long double)j;
	}
	I *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_CHEBYSHEV2) {
      long double bot, top;
      if (!(power[i]%2)) {
      top = 1; bot = 1;
      for (int j=2;j<=power[i];j+=2) {
	top *= (long double)(j-1);
	bot *= (long double)j;
      }
      bot *= (long double)(power[i]+2);
      I   *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_HERMITE||rule[i]==BURK_GENZKEISTER) {
      if (power[i]%2) {
	I *= 0.0;
      }
      else {
	long double value = 1.0;
	if ((power[i]-1)>=1) {
	  int n_copy = power[i]-1;
	  while (1<n_copy) {
	    value  *= (long double)n_copy;
	    n_copy -= 2;
	  }
	}
	I *= value*sqrt(M_PI)/powl(2.0,(long double)power[i]/2.0);
      }
    }
  }

// @HEADER
//                           Intrepid2 Package
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Questions? Contact Kyungjoo Kim  (example@nnthink.com), or
//                    Mauro Perego  (example@nnthink.com)
// @HEADER

/** \file
\brief  Unit test (CubatureDirect): correctness of
        integration of monomials for 1D reference cells.
\author Created by P. Bochev and D. Ridzal.
*/

#include "Intrepid2_CubatureTensorSorted.hpp"
#include "Intrepid2_Utils.hpp"
#include "Teuchos_oblackholestream.hpp"
#include "Teuchos_RCP.hpp"
#include "Teuchos_GlobalMPISession.hpp"

using namespace Intrepid2;

/*
  Computes integrals of monomials over a given reference cell.
*/
long double evalQuad(std::vector<int> power, int dimension,
		     std::vector<int> order,
		     std::vector<EIntrepidBurkardt> rule) {

  CubatureTensorSorted<long double> lineCub(dimension,order,rule,false);
  order[0]--; order[1]--;
  CubatureTensorSorted<long double> lineCub1(dimension,order,rule,false);
  lineCub.update(1.0,lineCub1,1.0);

  int size = lineCub.getNumPoints();
  FieldContainer<long double> cubPoints(size,dimension);
  FieldContainer<long double> cubWeights(size);
  lineCub.getCubature(cubPoints,cubWeights);

  int mid  = size/2;
  long double Q = 0.0;
  if (size%2) {
    Q  = cubWeights(mid);
    for (int i=0; i<dimension; i++) {
      Q *= powl(cubPoints(mid,i),(long double)power[i]);
    }
  }

  for (int i=0; i<mid; i++) {
    long double value1 = cubWeights(i);
    long double value2 = cubWeights(size-i-1);
    for (int j=0; j<dimension; j++) {
      value1 *= powl(cubPoints(i,j),(long double)power[j]);
      value2 *= powl(cubPoints(size-i-1,j),(long double)power[j]);
    }
    Q += value1+value2;
  }
  return Q;
}

long double evalInt(int dimension, std::vector<int> power,
		    std::vector<EIntrepidBurkardt> rule) {
  long double I = 1.0;

  return I;
}

int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);

  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  *outStream \
  << "===============================================================================\n" \
  << "|                                                                             |\n" \
  << "|                         Unit Test (CubatureTensorSorted)                    |\n" \
  << "|                                                                             |\n" \
  << "|     1) Computing integrals of monomials in 2D                               |\n" \
  << "|                                                                             |\n" \
  << "|  Questions? Contact  Drew Kouri (example@nnthink.com) or                     |\n" \
  << "|                      Denis Ridzal (example@nnthink.com).                     |\n" \
  << "|                                                                             |\n" \
  << "|  Intrepid's website: http://example.com           |\n" \
  << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
  << "|                                                                             |\n" \
  << "===============================================================================\n"\
  << "| TEST 12: integrals of monomials in 2D - Anisotropic but no growth rules     |\n"\
  << "===============================================================================\n";

  int dimension           = 2;
  int         errorFlag   = 0;
  long double reltol      = 1.0e+02*INTREPID_TOL;
  int         maxDeg      = 0;
  long double analyticInt = 0;
  long double testInt     = 0;
  int         maxOrder    = 20;
  std::vector<int> power(2,0);
  std::vector<EIntrepidBurkardt> rule1(2,BURK_CLENSHAWCURTIS);
  std::vector<int> order(2,0);

  *outStream << "\nIntegrals of monomials on a reference line (edge):\n";
  // compute and compare integrals
  try {
    for (int i=0; i<=maxOrder; i++) {
      maxDeg = i-2;

      order[0] = i; order[1] = i;
      for (int j=0; j <= maxDeg; j++) {
	power[0] = j;
	for (int k=0; k <= maxDeg; k++) {
	  power[1] = k;
	  analyticInt = 2.0*evalInt(dimension, power, rule1);
	  testInt     = evalQuad(power,dimension,order,rule1);

	  long double abstol  = (analyticInt == 0.0 ? reltol : std::fabs(reltol*analyticInt) );
	  long double absdiff = std::fabs(analyticInt - testInt);
	  *outStream << "Cubature order " << std::setw(2) << std::left << i
		     << " integrating "
		     << "x^" << std::setw(2) << std::left << j << "y^"
		     << std::setw(2) << std::left
		     << k <<  ":" << "   " << std::scientific
		     << std::setprecision(16) << testInt
		     << "   " << analyticInt << "   " << std::setprecision(4)
		     << absdiff << "   "
		     << "<?" << "   " << abstol << "\n";
	  if (absdiff > abstol) {
	    errorFlag++;
	    *outStream << std::right << std::setw(104) << "^^^^---FAILURE!\n";
	  }
	} // end for k
	*outStream << "\n";
      } // end for j
      *outStream << "\n";
    } // end for i
  }
  catch (std::logic_error &err) {
    *outStream << err.what() << "\n";
    errorFlag = -1;
  };

  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
Kokkos::finalize();
  return errorFlag;
}


// @HEADER
//                           Intrepid2 Package
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Questions? Contact Kyungjoo Kim  (example@nnthink.com), or
//                    Mauro Perego  (example@nnthink.com)
// @HEADER

/** \file
\brief  Unit test (CubatureDirect): correctness of
        integration of monomials for 1D reference cells.
\author Created by P. Bochev and D. Ridzal.
*/

#include "Intrepid2_CubatureTensorSorted.hpp"
#include "Intrepid2_Utils.hpp"
#include "Teuchos_oblackholestream.hpp"
#include "Teuchos_RCP.hpp"
#include "Teuchos_GlobalMPISession.hpp"

using namespace Intrepid2;

/*
  Computes integrals of monomials over a given reference cell.
*/
long double evalQuad(std::vector<int> power, int dimension,
		     std::vector<int> order,
		     std::vector<EIntrepidBurkardt> rule) {

  CubatureTensorSorted<long double> lineCub(dimension,order,rule,false);
  order[0]--; order[1]--;
  CubatureTensorSorted<long double> lineCub1(dimension,order,rule,false);
  lineCub.update(1.0,lineCub1,1.0);

  int size = lineCub.getNumPoints();
  FieldContainer<long double> cubPoints(size,dimension);
  FieldContainer<long double> cubWeights(size);
  lineCub.getCubature(cubPoints,cubWeights);

  int mid  = size/2;
  long double Q = 0.0;
  if (size%2) {
    Q  = cubWeights(mid);
    for (int i=0; i<dimension; i++) {
      Q *= powl(cubPoints(mid,i),(long double)power[i]);
    }
  }

  for (int i=0; i<mid; i++) {
    long double value1 = cubWeights(i);
    long double value2 = cubWeights(size-i-1);
    for (int j=0; j<dimension; j++) {
      value1 *= powl(cubPoints(i,j),(long double)power[j]);
      value2 *= powl(cubPoints(size-i-1,j),(long double)power[j]);
    }
    Q += value1+value2;
  }
  return Q;
}

long double evalInt(int dimension, std::vector<int> power,
		    std::vector<EIntrepidBurkardt> rule) {
  long double I = 1.0;

  for (int i=0; i<dimension; i++) {
    if (rule[i]==BURK_CLENSHAWCURTIS||rule[i]==BURK_FEJER2||
	rule[i]==BURK_LEGENDRE||rule[i]==BURK_PATTERSON ||
	rule[i]==BURK_TRAPEZOIDAL) {
      if (power[i]%2)
	I *= 0.0;
      else
	I *= 2.0/((long double)power[i]+1.0);
    }
    else if (rule[i]==BURK_LAGUERRE) {
      I *= tgammal((long double)(power[i]+1));
    }
    else if (rule[i]==BURK_CHEBYSHEV1) {
      long double bot, top;
      if (!(power[i]%2)) {
	top = 1; bot = 1;
	for (int j=2;j<=power[i];j+=2) {
	  top *= (long double)(j-1);
	  bot *= (long double)j;
	}
	I *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_CHEBYSHEV2) {
      long double bot, top;
      if (!(power[i]%2)) {
      top = 1; bot = 1;
      for (int j=2;j<=power[i];j+=2) {
	top *= (long double)(j-1);
	bot *= (long double)j;
      }
      bot *= (long double)(power[i]+2);
      I   *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_HERMITE||rule[i]==BURK_GENZKEISTER) {
      if (power[i]%2) {
	I *= 0.0;
      }
      else {
	long double value = 1.0;
	if ((power[i]-1)>=1) {
	  int n_copy = power[i]-1;
	  while (1<n_copy) {
	    value  *= (long double)n_copy;
	    n_copy -= 2;
	  }
	}
	I *= value*sqrt(M_PI)/powl(2.0,(long double)power[i]/2.0);
      }
    }
  }

int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);

  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  *outStream \
  << "===============================================================================\n" \
  << "|                                                                             |\n" \
  << "|                         Unit Test (CubatureTensorSorted)                    |\n" \
  << "|                                                                             |\n" \
  << "|     1) Computing integrals of monomials in 2D                               |\n" \
  << "|                                                                             |\n" \
  << "|  Questions? Contact  Drew Kouri (example@nnthink.com) or                     |\n" \
  << "|                      Denis Ridzal (example@nnthink.com).                     |\n" \
  << "|                                                                             |\n" \
  << "|  Intrepid's website: http://example.com           |\n" \
  << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
  << "|                                                                             |\n" \
  << "===============================================================================\n"\
  << "| TEST 12: integrals of monomials in 2D - Anisotropic but no growth rules     |\n"\
  << "===============================================================================\n";

  int dimension           = 2;
  int         errorFlag   = 0;
  long double reltol      = 1.0e+02*INTREPID_TOL;
  int         maxDeg      = 0;
  long double analyticInt = 0;
  long double testInt     = 0;
  int         maxOrder    = 20;
  std::vector<int> power(2,0);
  std::vector<EIntrepidBurkardt> rule1(2,BURK_CLENSHAWCURTIS);
  std::vector<int> order(2,0);

  *outStream << "\nIntegrals of monomials on a reference line (edge):\n";
  // compute and compare integrals
  try {
    for (int i=0; i<=maxOrder; i++) {
      maxDeg = i-2;

      order[0] = i; order[1] = i;
      for (int j=0; j <= maxDeg; j++) {
	power[0] = j;
	for (int k=0; k <= maxDeg; k++) {
	  power[1] = k;
	  analyticInt = 2.0*evalInt(dimension, power, rule1);
	  testInt     = evalQuad(power,dimension,order,rule1);

	  long double abstol  = (analyticInt == 0.0 ? reltol : std::fabs(reltol*analyticInt) );
	  long double absdiff = std::fabs(analyticInt - testInt);
	  *outStream << "Cubature order " << std::setw(2) << std::left << i
		     << " integrating "
		     << "x^" << std::setw(2) << std::left << j << "y^"
		     << std::setw(2) << std::left
		     << k <<  ":" << "   " << std::scientific
		     << std::setprecision(16) << testInt
		     << "   " << analyticInt << "   " << std::setprecision(4)
		     << absdiff << "   "
		     << "<?" << "   " << abstol << "\n";
	  if (absdiff > abstol) {
	    errorFlag++;
	    *outStream << std::right << std::setw(104) << "^^^^---FAILURE!\n";
	  }
	} // end for k
	*outStream << "\n";
      } // end for j
      *outStream << "\n";
    } // end for i
  }
  catch (std::logic_error &err) {
    *outStream << err.what() << "\n";
    errorFlag = -1;
  };

  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
Kokkos::finalize();
  return errorFlag;
}


// @HEADER
//                           Intrepid2 Package
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Questions? Contact Kyungjoo Kim  (example@nnthink.com), or
//                    Mauro Perego  (example@nnthink.com)
// @HEADER

/** \file
\brief  Unit test (CubatureDirect): correctness of
        integration of monomials for 1D reference cells.
\author Created by P. Bochev and D. Ridzal.
*/

#include "Intrepid2_CubatureTensorSorted.hpp"
#include "Intrepid2_Utils.hpp"
#include "Teuchos_oblackholestream.hpp"
#include "Teuchos_RCP.hpp"
#include "Teuchos_GlobalMPISession.hpp"

using namespace Intrepid2;

/*
  Computes integrals of monomials over a given reference cell.
*/
long double evalQuad(std::vector<int> power, int dimension,
		     std::vector<int> order,
		     std::vector<EIntrepidBurkardt> rule) {

  CubatureTensorSorted<long double> lineCub(dimension,order,rule,false);
  order[0]--; order[1]--;
  CubatureTensorSorted<long double> lineCub1(dimension,order,rule,false);
  lineCub.update(1.0,lineCub1,1.0);

  int size = lineCub.getNumPoints();
  FieldContainer<long double> cubPoints(size,dimension);
  FieldContainer<long double> cubWeights(size);
  lineCub.getCubature(cubPoints,cubWeights);

  int mid  = size/2;
  long double Q = 0.0;
  if (size%2) {
    Q  = cubWeights(mid);
    for (int i=0; i<dimension; i++) {
      Q *= powl(cubPoints(mid,i),(long double)power[i]);
    }
  }

  for (int i=0; i<mid; i++) {
    long double value1 = cubWeights(i);
    long double value2 = cubWeights(size-i-1);
    for (int j=0; j<dimension; j++) {
      value1 *= powl(cubPoints(i,j),(long double)power[j]);
      value2 *= powl(cubPoints(size-i-1,j),(long double)power[j]);
    }
    Q += value1+value2;
  }
  return

}

long double evalInt(int dimension, std::vector<int> power,
		    std::vector<EIntrepidBurkardt> rule) {
  long double I = 1.0;

  for (int i=0; i<dimension; i++) {
    if (rule[i]==BURK_CLENSHAWCURTIS||rule[i]==BURK_FEJER2||
	rule[i]==BURK_LEGENDRE||rule[i]==BURK_PATTERSON ||
	rule[i]==BURK_TRAPEZOIDAL) {
      if (power[i]%2)
	I *= 0.0;
      else
	I *= 2.0/((long double)power[i]+1.0);
    }
    else if (rule[i]==BURK_LAGUERRE) {
      I *= tgammal((long double)(power[i]+1));
    }
    else if (rule[i]==BURK_CHEBYSHEV1) {
      long double bot, top;
      if (!(power[i]%2)) {
	top = 1; bot = 1;
	for (int j=2;j<=power[i];j+=2) {
	  top *= (long double)(j-1);
	  bot *= (long double)j;
	}
	I *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_CHEBYSHEV2) {
      long double bot, top;
      if (!(power[i]%2)) {
      top = 1; bot = 1;
      for (int j=2;j<=power[i];j+=2) {
	top *= (long double)(j-1);
	bot *= (long double)j;
      }
      bot *= (long double)(power[i]+2);
      I   *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_HERMITE||rule[i]==BURK_GENZKEISTER) {
      if (power[i]%2) {
	I *= 0.0;
      }
      else {
	long double value = 1.0;
	if ((power[i]-1)>=1) {
	  int n_copy = power[i]-1;
	  while (1<n_copy) {
	    value  *= (long double)n_copy;
	    n_copy -= 2;
	  }
	}
	I *= value*sqrt(M_PI)/powl(2.0,(long double)power[i]/2.0);
      }
    }
  }
  return I;
}

int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);

  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  *outStream \
  << "===============================================================================\n" \
  << "|                                                                             |\n" \
  << "|                         Unit Test (CubatureTensorSorted)                    |\n" \
  << "|                                                                             |\n" \
  << "|     1) Computing integrals of monomials in 2D                               |\n" \
  << "|                                                                             |\n" \
  << "|  Questions? Contact  Drew Kouri (example@nnthink.com) or                     |\n" \
  << "|                      Denis Ridzal (example@nnthink.com).                     |\n" \
  << "|                                                                             |\n" \
  << "|  Intrepid's website: http://example.com           |\n" \
  << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
  << "|                                                                             |\n" \
  << "===============================================================================\n"\
  << "| TEST 12: integrals of monomials in 2D - Anisotropic but no growth rules     |\n"\
  << "===============================================================================\n";

  int dimension           = 2;
  int         errorFlag   = 0;
  long double reltol      = 1.0e+02*INTREPID_TOL;
  int         maxDeg      = 0;
  long double analyticInt = 0;
  long double testInt     = 0;
  int         maxOrder    = 20;
  std::vector<int> power(2,0);
  std::vector<EIntrepidBurkardt> rule1(2,BURK_CLENSHAWCURTIS);
  std::vector<int> order(2,0);

  *outStream << "\nIntegrals of monomials on a reference line (edge):\n";
  // compute and compare integrals
  try {
    for (int i=0; i<=maxOrder; i++) {
      maxDeg = i-2;

      order[0] = i; order[1] = i;
      for (int j=0; j <= maxDeg; j++) {
	power[0] = j;
	for (int k=0; k <= maxDeg; k++) {
	  power[1] = k;
	  analyticInt = 2.0*evalInt(dimension, power, rule1);
	  testInt     = evalQuad(power,dimension,order,rule1);

	  long double abstol  = (analyticInt == 0.0 ? reltol : std::fabs(reltol*analyticInt) );
	  long double absdiff = std::fabs(analyticInt - testInt);
	  *outStream << "Cubature order " << std::setw(2) << std::left << i
		     << " integrating "
		     << "x^" << std::setw(2) << std::left << j << "y^"
		     << std::setw(2) << std::left
		     << k <<  ":" << "   " << std::scientific
		     << std::setprecision(16) << testInt
		     << "   " << analyticInt << "   " << std::setprecision(4)
		     << absdiff << "   "
		     << "<?" << "   " << abstol << "\n";
	  if (absdiff > abstol) {
	    errorFlag++;
	    *outStream << std::right << std::setw(104) << "^^^^---FAILURE!\n";
	  }
	} // end for k
	*outStream << "\n";
      } // end for j
      *outStream << "\n";
    } // end for i
  }
  catch (std::logic_error &err) {
    *outStream << err.what() << "\n";
    errorFlag = -1;
  };

  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
Kokkos::finalize();
  return errorFlag;
}


if (power[i]%2)
	I *= 0.0;
      else
	I *= 2.0/((long double)power[i]+1.0);

// @HEADER
//                           Intrepid2 Package
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Questions? Contact Kyungjoo Kim  (example@nnthink.com), or
//                    Mauro Perego  (example@nnthink.com)
// @HEADER

/** \file
\brief  Unit test (CubatureDirect): correctness of
        integration of monomials for 1D reference cells.
\author Created by P. Bochev and D. Ridzal.
*/

#include "Intrepid2_CubatureTensorSorted.hpp"
#include "Intrepid2_Utils.hpp"
#include "Teuchos_oblackholestream.hpp"
#include "Teuchos_RCP.hpp"
#include "Teuchos_GlobalMPISession.hpp"

using namespace Intrepid2;

/*
  Computes integrals of monomials over a given reference cell.
*/
long double evalQuad(std::vector<int> power, int dimension,
		     std::vector<int> order,
		     std::vector<EIntrepidBurkardt> rule) {

  CubatureTensorSorted<long double> lineCub(dimension,order,rule,false);
  order[0]--; order[1]--;
  CubatureTensorSorted<long double> lineCub1(dimension,order,rule,false);
  lineCub.update(1.0,lineCub1,1.0);

  int size = lineCub.getNumPoints();
  FieldContainer<long double> cubPoints(size,dimension);
  FieldContainer<long double> cubWeights(size);
  lineCub.getCubature(cubPoints,cubWeights);

  int mid  = size/2;
  long double Q = 0.0;
  if (size%2) {
    Q  = cubWeights(mid);
    for (int i=0; i<dimension; i++) {
      Q *= powl(cubPoints(mid,i),(long double)power[i]);
    }
  }

  for (int i=0; i<mid; i++) {
    long double value1 = cubWeights(i);
    long double value2 = cubWeights(size-i-1);
    for (int j=0; j<dimension; j++) {
      value1 *= powl(cubPoints(i,j),(long double)power[j]);
      value2 *= powl(cubPoints(size-i-1,j),(long double)power[j]);
    }
    Q += value1+value2;
  }
  return Q;
}

long double evalInt(int dimension, std::vector<int> power,
		    std::vector<EIntrepidBurkardt> rule) {
  long double I = 1.0;

  for (int i=0; i<dimension; i++) {
    if (rule[i]==BURK_CLENSHAWCURTIS||rule[i]==BURK_FEJER2||
	rule[i]==BURK_LEGENDRE||rule[i]==BURK_PATTERSON ||
	rule[i]==BURK_TRAPEZOIDAL) {

    }
    else if (rule[i]==BURK_LAGUERRE) {
      I *= tgammal((long double)(power[i]+1));
    }
    else if (rule[i]==BURK_CHEBYSHEV1) {
      long double bot, top;
      if (!(power[i]%2)) {
	top = 1; bot = 1;
	for (int j=2;j<=power[i];j+=2) {
	  top *= (long double)(j-1);
	  bot *= (long double)j;
	}
	I *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_CHEBYSHEV2) {
      long double bot, top;
      if (!(power[i]%2)) {
      top = 1; bot = 1;
      for (int j=2;j<=power[i];j+=2) {
	top *= (long double)(j-1);
	bot *= (long double)j;
      }
      bot *= (long double)(power[i]+2);
      I   *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_HERMITE||rule[i]==BURK_GENZKEISTER) {
      if (power[i]%2) {
	I *= 0.0;
      }
      else {
	long double value = 1.0;
	if ((power[i]-1)>=1) {
	  int n_copy = power[i]-1;
	  while (1<n_copy) {
	    value  *= (long double)n_copy;
	    n_copy -= 2;
	  }
	}
	I *= value*sqrt(M_PI)/powl(2.0,(long double)power[i]/2.0);
      }
    }
  }
  return I;
}

int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);

  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  *outStream \
  << "===============================================================================\n" \
  << "|                                                                             |\n" \
  << "|                         Unit Test (CubatureTensorSorted)                    |\n" \
  << "|                                                                             |\n" \
  << "|     1) Computing integrals of monomials in 2D                               |\n" \
  << "|                                                                             |\n" \
  << "|  Questions? Contact  Drew Kouri (example@nnthink.com) or                     |\n" \
  << "|                      Denis Ridzal (example@nnthink.com).                     |\n" \
  << "|                                                                             |\n" \
  << "|  Intrepid's website: http://example.com           |\n" \
  << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
  << "|                                                                             |\n" \
  << "===============================================================================\n"\
  << "| TEST 12: integrals of monomials in 2D - Anisotropic but no growth rules     |\n"\
  << "===============================================================================\n";

  int dimension           = 2;
  int         errorFlag   = 0;
  long double reltol      = 1.0e+02*INTREPID_TOL;
  int         maxDeg      = 0;
  long double analyticInt = 0;
  long double testInt     = 0;
  int         maxOrder    = 20;
  std::vector<int> power(2,0);
  std::vector<EIntrepidBurkardt> rule1(2,BURK_CLENSHAWCURTIS);
  std::vector<int> order(2,0);

  *outStream << "\nIntegrals of monomials on a reference line (edge):\n";
  // compute and compare integrals
  try {
    for (int i=0; i<=maxOrder; i++) {
      maxDeg = i-2;

      order[0] = i; order[1] = i;
      for (int j=0; j <= maxDeg; j++) {
	power[0] = j;
	for (int k=0; k <= maxDeg; k++) {
	  power[1] = k;
	  analyticInt = 2.0*evalInt(dimension, power, rule1);
	  testInt     = evalQuad(power,dimension,order,rule1);

	  long double abstol  = (analyticInt == 0.0 ? reltol : std::fabs(reltol*analyticInt) );
	  long double absdiff = std::fabs(analyticInt - testInt);
	  *outStream << "Cubature order " << std::setw(2) << std::left << i
		     << " integrating "
		     << "x^" << std::setw(2) << std::left << j << "y^"
		     << std::setw(2) << std::left
		     << k <<  ":" << "   " << std::scientific
		     << std::setprecision(16) << testInt
		     << "   " << analyticInt << "   " << std::setprecision(4)
		     << absdiff << "   "
		     << "<?" << "   " << abstol << "\n";
	  if (absdiff > abstol) {
	    errorFlag++;
	    *outStream << std::right << std::setw(104) << "^^^^---FAILURE!\n";
	  }
	} // end for k
	*outStream << "\n";
      } // end for j
      *outStream << "\n";
    } // end for i
  }
  catch (std::logic_error &err) {
    *outStream << err.what() << "\n";
    errorFlag = -1;
  };

  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
Kokkos::finalize();
  return errorFlag;
}


// @HEADER
//                           Intrepid2 Package
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Questions? Contact Kyungjoo Kim  (example@nnthink.com), or
//                    Mauro Perego  (example@nnthink.com)
// @HEADER

/** \file
\brief  Unit test (CubatureDirect): correctness of
        integration of monomials for 1D reference cells.
\author Created by P. Bochev and D. Ridzal.
*/

#include "Intrepid2_CubatureTensorSorted.hpp"
#include "Intrepid2_Utils.hpp"
#include "Teuchos_oblackholestream.hpp"
#include "Teuchos_RCP.hpp"
#include "Teuchos_GlobalMPISession.hpp"

using namespace Intrepid2;

/*
  Computes integrals of monomials over a given reference cell.
*/
long double evalQuad(std::vector<int> power, int dimension,
		     std::vector<int> order,
		     std::vector<EIntrepidBurkardt> rule) {

  CubatureTensorSorted<long double> lineCub(dimension,order,rule,false);
  order[0]--; order[1]--;
  CubatureTensorSorted<long double> lineCub1(dimension,order,rule,false);
  lineCub.update(1.0,lineCub1,1.0);

  int size = lineCub.getNumPoints();
  FieldContainer<long double> cubPoints(size,dimension);
  FieldContainer<long double> cubWeights(size);
  lineCub.getCubature(cubPoints,cubWeights);

  int mid  = size/2;
  long double Q = 0.0;
  if (size%2) {
    Q  = cubWeights(mid);
    for (int i=0; i<dimension; i++) {
      Q *= powl(cubPoints(mid,i),(long double)power[i]);
    }
  }

  for (int i=0; i<mid; i++) {
    long double value1 = cubWeights(i);
    long double value2 = cubWeights(size-i-1);
    for (int j=0; j<dimension; j++) {
      value1 *= powl(cubPoints(i,j),(long double)power[j]);
      value2 *= powl(cubPoints(size-i-1,j),(long double)power[j]);
    }
    Q += value1+value2;
  }
  return Q;
}

long double evalInt(int dimension, std::vector<int> power,
		    std::vector<EIntrepidBurkardt> rule) {
  long double I = 1.0;

  for (int i=0; i<dimension; i++) {
    if (rule[i]==BURK_CLENSHAWCURTIS||rule[i]==BURK_FEJER2||
	rule[i]==BURK_LEGENDRE||rule[i]==BURK_PATTERSON ||
	rule[i]==BURK_TRAPEZOIDAL) {
      if (power[i]%2)
	I *= 0.0;
      else
	I *= 2.0/((long double)power[i]+1.0);
    }
    else if (rule[i]==BURK_LAGUERRE) {
      I *= tgammal((long double)(power[i]+1));
    }
    else if (rule[i]==BURK_CHEBYSHEV1) {
      long double bot, top;
      if (!(power[i]%2)) {
	top = 1; bot = 1;
	for (int j=2;j<=power[i];j+=2) {
	  top *= (long double)(j-1);
	  bot *= (long double)j;
	}
	I *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_CHEBYSHEV2) {
      long double bot, top;
      if (!(power[i]%2)) {
      top = 1; bot = 1;

      bot *= (long double)(power[i]+2);
      I   *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_HERMITE||rule[i]==BURK_GENZKEISTER) {
      if (power[i]%2) {
	I *= 0.0;
      }
      else {
	long double value = 1.0;
	if ((power[i]-1)>=1) {
	  int n_copy = power[i]-1;
	  while (1<n_copy) {
	    value  *= (long double)n_copy;
	    n_copy -= 2;
	  }
	}
	I *= value*sqrt(M_PI)/powl(2.0,(long double)power[i]/2.0);
      }
    }
  }
  return I;
}

int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);

  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  *outStream \
  << "===============================================================================\n" \
  << "|                                                                             |\n" \
  << "|                         Unit Test (CubatureTensorSorted)                    |\n" \
  << "|                                                                             |\n" \
  << "|     1) Computing integrals of monomials in 2D                               |\n" \
  << "|                                                                             |\n" \
  << "|  Questions? Contact  Drew Kouri (example@nnthink.com) or                     |\n" \
  << "|                      Denis Ridzal (example@nnthink.com).                     |\n" \
  << "|                                                                             |\n" \
  << "|  Intrepid's website: http://example.com           |\n" \
  << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
  << "|                                                                             |\n" \
  << "===============================================================================\n"\
  << "| TEST 12: integrals of monomials in 2D - Anisotropic but no growth rules     |\n"\
  << "===============================================================================\n";

  int dimension           = 2;
  int         errorFlag   = 0;
  long double reltol      = 1.0e+02*INTREPID_TOL;
  int         maxDeg      = 0;
  long double analyticInt = 0;
  long double testInt     = 0;
  int         maxOrder    = 20;
  std::vector<int> power(2,0);
  std::vector<EIntrepidBurkardt> rule1(2,BURK_CLENSHAWCURTIS);
  std::vector<int> order(2,0);

  *outStream << "\nIntegrals of monomials on a reference line (edge):\n";
  // compute and compare integrals
  try {
    for (int i=0; i<=maxOrder; i++) {
      maxDeg = i-2;

      order[0] = i; order[1] = i;
      for (int j=0; j <= maxDeg; j++) {
	power[0] = j;
	for (int k=0; k <= maxDeg; k++) {
	  power[1] = k;
	  analyticInt = 2.0*evalInt(dimension, power, rule1);
	  testInt     = evalQuad(power,dimension,order,rule1);

	  long double abstol  = (analyticInt == 0.0 ? reltol : std::fabs(reltol*analyticInt) );
	  long double absdiff = std::fabs(analyticInt - testInt);
	  *outStream << "Cubature order " << std::setw(2) << std::left << i
		     << " integrating "
		     << "x^" << std::setw(2) << std::left << j << "y^"
		     << std::setw(2) << std::left
		     << k <<  ":" << "   " << std::scientific
		     << std::setprecision(16) << testInt
		     << "   " << analyticInt << "   " << std::setprecision(4)
		     << absdiff << "   "
		     << "<?" << "   " << abstol << "\n";
	  if (absdiff > abstol) {
	    errorFlag++;
	    *outStream << std::right << std::setw(104) << "^^^^---FAILURE!\n";
	  }
	} // end for k
	*outStream << "\n";
      } // end for j
      *outStream << "\n";
    } // end for i
  }
  catch (std::logic_error &err) {
    *outStream << err.what() << "\n";
    errorFlag = -1;
  };

  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
Kokkos::finalize();
  return errorFlag;
}


while (1<n_copy) {
	    value  *= (long double)n_copy;
	    n_copy -= 2;
	  }

// @HEADER
//                           Intrepid2 Package
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Questions? Contact Kyungjoo Kim  (example@nnthink.com), or
//                    Mauro Perego  (example@nnthink.com)
// @HEADER

/** \file
\brief  Unit test (CubatureDirect): correctness of
        integration of monomials for 1D reference cells.
\author Created by P. Bochev and D. Ridzal.
*/

#include "Intrepid2_CubatureTensorSorted.hpp"
#include "Intrepid2_Utils.hpp"
#include "Teuchos_oblackholestream.hpp"
#include "Teuchos_RCP.hpp"
#include "Teuchos_GlobalMPISession.hpp"

using namespace Intrepid2;

/*
  Computes integrals of monomials over a given reference cell.
*/
long double evalQuad(std::vector<int> power, int dimension,
		     std::vector<int> order,
		     std::vector<EIntrepidBurkardt> rule) {

  CubatureTensorSorted<long double> lineCub(dimension,order,rule,false);
  order[0]--; order[1]--;
  CubatureTensorSorted<long double> lineCub1(dimension,order,rule,false);
  lineCub.update(1.0,lineCub1,1.0);

  int size = lineCub.getNumPoints();
  FieldContainer<long double> cubPoints(size,dimension);
  FieldContainer<long double> cubWeights(size);
  lineCub.getCubature(cubPoints,cubWeights);

  int mid  = size/2;
  long double Q = 0.0;
  if (size%2) {
    Q  = cubWeights(mid);
    for (int i=0; i<dimension; i++) {
      Q *= powl(cubPoints(mid,i),(long double)power[i]);
    }
  }

  for (int i=0; i<mid; i++) {
    long double value1 = cubWeights(i);
    long double value2 = cubWeights(size-i-1);
    for (int j=0; j<dimension; j++) {
      value1 *= powl(cubPoints(i,j),(long double)power[j]);
      value2 *= powl(cubPoints(size-i-1,j),(long double)power[j]);
    }
    Q += value1+value2;
  }
  return Q;
}

long double evalInt(int dimension, std::vector<int> power,
		    std::vector<EIntrepidBurkardt> rule) {
  long double I = 1.0;

  for (int i=0; i<dimension; i++) {
    if (rule[i]==BURK_CLENSHAWCURTIS||rule[i]==BURK_FEJER2||
	rule[i]==BURK_LEGENDRE||rule[i]==BURK_PATTERSON ||
	rule[i]==BURK_TRAPEZOIDAL) {
      if (power[i]%2)
	I *= 0.0;
      else
	I *= 2.0/((long double)power[i]+1.0);
    }
    else if (rule[i]==BURK_LAGUERRE) {
      I *= tgammal((long double)(power[i]+1));
    }
    else if (rule[i]==BURK_CHEBYSHEV1) {
      long double bot, top;
      if (!(power[i]%2)) {
	top = 1; bot = 1;
	for (int j=2;j<=power[i];j+=2) {
	  top *= (long double)(j-1);
	  bot *= (long double)j;
	}
	I *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_CHEBYSHEV2) {
      long double bot, top;
      if (!(power[i]%2)) {
      top = 1; bot = 1;
      for (int j=2;j<=power[i];j+=2) {
	top *= (long double)(j-1);
	bot *= (long double)j;
      }
      bot *= (long double)(power[i]+2);
      I   *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_HERMITE||rule[i]==BURK_GENZKEISTER) {
      if (power[i]%2) {
	I *= 0.0;
      }
      else {
	long double value = 1.0;
	if ((power[i]-1)>=1) {
	  int n_copy = power[i]-1;

	}
	I *= value*sqrt(M_PI)/powl(2.0,(long double)power[i]/2.0);
      }
    }
  }
  return I;
}

int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);

  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  *outStream \
  << "===============================================================================\n" \
  << "|                                                                             |\n" \
  << "|                         Unit Test (CubatureTensorSorted)                    |\n" \
  << "|                                                                             |\n" \
  << "|     1) Computing integrals of monomials in 2D                               |\n" \
  << "|                                                                             |\n" \
  << "|  Questions? Contact  Drew Kouri (example@nnthink.com) or                     |\n" \
  << "|                      Denis Ridzal (example@nnthink.com).                     |\n" \
  << "|                                                                             |\n" \
  << "|  Intrepid's website: http://example.com           |\n" \
  << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
  << "|                                                                             |\n" \
  << "===============================================================================\n"\
  << "| TEST 12: integrals of monomials in 2D - Anisotropic but no growth rules     |\n"\
  << "===============================================================================\n";

  int dimension           = 2;
  int         errorFlag   = 0;
  long double reltol      = 1.0e+02*INTREPID_TOL;
  int         maxDeg      = 0;
  long double analyticInt = 0;
  long double testInt     = 0;
  int         maxOrder    = 20;
  std::vector<int> power(2,0);
  std::vector<EIntrepidBurkardt> rule1(2,BURK_CLENSHAWCURTIS);
  std::vector<int> order(2,0);

  *outStream << "\nIntegrals of monomials on a reference line (edge):\n";
  // compute and compare integrals
  try {
    for (int i=0; i<=maxOrder; i++) {
      maxDeg = i-2;

      order[0] = i; order[1] = i;
      for (int j=0; j <= maxDeg; j++) {
	power[0] = j;
	for (int k=0; k <= maxDeg; k++) {
	  power[1] = k;
	  analyticInt = 2.0*evalInt(dimension, power, rule1);
	  testInt     = evalQuad(power,dimension,order,rule1);

	  long double abstol  = (analyticInt == 0.0 ? reltol : std::fabs(reltol*analyticInt) );
	  long double absdiff = std::fabs(analyticInt - testInt);
	  *outStream << "Cubature order " << std::setw(2) << std::left << i
		     << " integrating "
		     << "x^" << std::setw(2) << std::left << j << "y^"
		     << std::setw(2) << std::left
		     << k <<  ":" << "   " << std::scientific
		     << std::setprecision(16) << testInt
		     << "   " << analyticInt << "   " << std::setprecision(4)
		     << absdiff << "   "
		     << "<?" << "   " << abstol << "\n";
	  if (absdiff > abstol) {
	    errorFlag++;
	    *outStream << std::right << std::setw(104) << "^^^^---FAILURE!\n";
	  }
	} // end for k
	*outStream << "\n";
      } // end for j
      *outStream << "\n";
    } // end for i
  }
  catch (std::logic_error &err) {
    *outStream << err.what() << "\n";
    errorFlag = -1;
  };

  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
Kokkos::finalize();
  return errorFlag;
}


// @HEADER
//                           Intrepid2 Package
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Questions? Contact Kyungjoo Kim  (example@nnthink.com), or
//                    Mauro Perego  (example@nnthink.com)
// @HEADER

/** \file
\brief  Unit test (CubatureDirect): correctness of
        integration of monomials for 1D reference cells.
\author Created by P. Bochev and D. Ridzal.
*/

#include "Intrepid2_CubatureTensorSorted.hpp"
#include "Intrepid2_Utils.hpp"
#include "Teuchos_oblackholestream.hpp"
#include "Teuchos_RCP.hpp"
#include "Teuchos_GlobalMPISession.hpp"

using namespace Intrepid2;

/*
  Computes integrals of monomials over a given reference cell.
*/
long double evalQuad(std::vector<int> power, int dimension,
		     std::vector<int> order,
		     std::vector<EIntrepidBurkardt> rule) {

  CubatureTensorSorted<long double> lineCub(dimension,order,rule,false);
  order[0]--; order[1]--;
  CubatureTensorSorted<long double> lineCub1(dimension,order,rule,false);
  lineCub.update(1.0,lineCub1,1.0);

  int size = lineCub.getNumPoints();
  FieldContainer<long double> cubPoints(size,dimension);
  FieldContainer<long double> cubWeights(size);
  lineCub.getCubature(cubPoints,cubWeights);

  int mid  = size/2;
  long double Q = 0.0;
  if (size%2) {
    Q  = cubWeights(mid);
    for (int i=0; i<dimension; i++) {
      Q *= powl(cubPoints(mid,i),(long double)power[i]);
    }
  }

  for (int i=0; i<mid; i++) {
    long double value1 = cubWeights(i);
    long double value2 = cubWeights(size-i-1);
    for (int j=0; j<dimension; j++) {
      value1 *= powl(cubPoints(i,j),(long double)power[j]);
      value2 *= powl(cubPoints(size-i-1,j),(long double)power[j]);
    }
    Q += value1+value2;
  }
  return Q;
}

long double evalInt(int dimension, std::vector<int> power,
		    std::vector<EIntrepidBurkardt> rule) {
  long double I = 1.0;

  for (int i=0; i<dimension; i++) {
    if (rule[i]==BURK_CLENSHAWCURTIS||rule[i]==BURK_FEJER2||
	rule[i]==BURK_LEGENDRE||rule[i]==BURK_PATTERSON ||
	rule[i]==BURK_TRAPEZOIDAL) {
      if (power[i]%2)
	I *= 0.0;
      else
	I *= 2.0/((long double)power[i]+1.0);
    }
    else if (rule[i]==BURK_LAGUERRE) {
      I *= tgammal((long double)(power[i]+1));
    }
    else if (rule[i]==BURK_CHEBYSHEV1) {
      long double bot, top;
      if (!(power[i]%2)) {
	top = 1; bot = 1;
	for (int j=2;j<=power[i];j+=2) {
	  top *= (long double)(j-1);
	  bot *= (long double)j;
	}
	I *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_CHEBYSHEV2) {
      long double bot, top;
      if (!(power[i]%2)) {
      top = 1; bot = 1;
      for (int j=2;j<=power[i];j+=2) {
	top *= (long double)(j-1);
	bot *= (long double)j;
      }
      bot *= (long double)(power[i]+2);
      I   *= M_PI*top/bot;
      }
      else {
	I *= 0.0;
      }
    }
    else if (rule[i]==BURK_HERMITE||rule[i]==BURK_GENZKEISTER) {
      if (power[i]%2) {
	I *= 0.0;
      }
      else {
	long double v

alue = 1.0;
	if ((power[i]-1)>=1) {
	  int n_copy = power[i]-1;
	  while (1<n_copy) {
	    value  *= (long double)n_copy;
	    n_copy -= 2;
	  }
	}
	I *= value*sqrt(M_PI)/powl(2.0,(long double)power[i]/2.0);
      }
    }
  }
  return I;
}

int main(int argc, char *argv[]) {

  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
Kokkos::initialize();
  // This little trick lets us print to std::cout only if
  // a (dummy) command-line argument is provided.
  int iprint     = argc - 1;
  Teuchos::RCP<std::ostream> outStream;
  Teuchos::oblackholestream bhs; // outputs nothing
  if (iprint > 0)
    outStream = Teuchos::rcp(&std::cout, false);
  else
    outStream = Teuchos::rcp(&bhs, false);

  // Save the format state of the original std::cout.
  Teuchos::oblackholestream oldFormatState;
  oldFormatState.copyfmt(std::cout);

  *outStream \
  << "===============================================================================\n" \
  << "|                                                                             |\n" \
  << "|                         Unit Test (CubatureTensorSorted)                    |\n" \
  << "|                                                                             |\n" \
  << "|     1) Computing integrals of monomials in 2D                               |\n" \
  << "|                                                                             |\n" \
  << "|  Questions? Contact  Drew Kouri (example@nnthink.com) or                     |\n" \
  << "|                      Denis Ridzal (example@nnthink.com).                     |\n" \
  << "|                                                                             |\n" \
  << "|  Intrepid's website: http://example.com           |\n" \
  << "|  Trilinos website:   http://trilinos.sandia.gov                             |\n" \
  << "|                                                                             |\n" \
  << "===============================================================================\n"\
  << "| TEST 12: integrals of monomials in 2D - Anisotropic but no growth rules     |\n"\
  << "===============================================================================\n";

  int dimension           = 2;
  int         errorFlag   = 0;
  long double reltol      = 1.0e+02*INTREPID_TOL;
  int         maxDeg      = 0;
  long double analyticInt = 0;
  long double testInt     = 0;
  int         maxOrder    = 20;
  std::vector<int> power(2,0);
  std::vector<EIntrepidBurkardt> rule1(2,BURK_CLENSHAWCURTIS);
  std::vector<int> order(2,0);

  *outStream << "\nIntegrals of monomials on a reference line (edge):\n";
  // compute and compare integrals
  try {
    for (int i=0; i<=maxOrder; i++) {
      maxDeg = i-2;

      order[0] = i; order[1] = i;
      for (int j=0; j <= maxDeg; j++) {
	power[0] = j;
	for (int k=0; k <= maxDeg; k++) {
	  power[1] = k;
	  analyticInt = 2.0*evalInt(dimension, power, rule1);
	  testInt     = evalQuad(power,dimension,order,rule1);

	  long double abstol  = (analyticInt == 0.0 ? reltol : std::fabs(reltol*analyticInt) );
	  long double absdiff = std::fabs(analyticInt - testInt);
	  *outStream << "Cubature order " << std::setw(2) << std::left << i
		     << " integrating "
		     << "x^" << std::setw(2) << std::left << j << "y^"
		     << std::setw(2) << std::left
		     << k <<  ":" << "   " << std::scientific
		     << std::setprecision(16) << testInt
		     << "   " << analyticInt << "   " << std::setprecision(4)
		     << absdiff << "   "
		     << "<?" << "   " << abstol << "\n";
	  if (absdiff > abstol) {
	    errorFlag++;
	    *outStream << std::right << std::setw(104) << "^^^^---FAILURE!\n";
	  }
	} // end for k
	*outStream << "\n";
      } // end for j
      *outStream << "\n";
    } // end for i
  }
  catch (std::logic_error &err) {
    *outStream << err.what() << "\n";
    errorFlag = -1;
  };

  if (errorFlag != 0)
    std::cout << "End Result: TEST FAILED\n";
  else
    std::cout << "End Result: TEST PASSED\n";

  // reset format state of std::cout
  std::cout.copyfmt(oldFormatState);
Kokkos::finalize();
  return errorFlag;
}


{
}

bool LaunchAttachCommand::executeImpl(DebuggerSession* /*session*/,
                                      folly::dynamic* responseMsg) {
  folly::dynamic& message = getMessage();
  const folly::dynamic& args = tryGetObject(message, "arguments", s_emptyArgs);
  const std::string emptyString = std::string("");

  const auto& sandboxUser =
    tryGetString(args, "sandboxUser", emptyString);

  const auto& sandboxName =
    tryGetString(args, "sandboxName", "default");

  const auto& startupDoc =
    tryGetString(args, "startupDocumentPath", emptyString);

  bool displayStartupMsg =
    tryGetBool(args, "displayConsoleStartupMsg", true);

  bool showDummyOnAsyncPause =
     tryGetBool(args, "showDummyOnAsyncPause", false);

  bool warnOnInterceptedFunctions =
    tryGetBool(args, "warnOnInterceptedFunctions", false);

  bool notifyOnBpCalibration =
    tryGetBool(args, "notifyOnBpCalibration", false);

  bool disableUniqueVarRef =
    tryGetBool(args, "disableUniqueVarRef", false);

  bool disableDummyPsPs =
    tryGetBool(args, "disableDummyPsPs", false);

  bool disableStdoutRedirection =
    tryGetBool(args, "disableStdoutRedirection", false);

  const auto& logFilePath =
    tryGetString(args, "logFilePath", emptyString);

  const auto debuggerSessionAuthToken =
    tryGetString(args, "debuggerSessionAuthToken", emptyString);

  auto maxReturnedStringLength =
    tryGetInt(args, "maxReturnedStringLength", 32 * 1024);

  if (!logFilePath.empty()) {
    // Re-open logging using the file path specified by the client.
    int result = VSDebugLogger::InitializeLogging(logFilePath);
    if (result != 0) {
      std::string msg = "Opening log file ";
      msg += logFilePath.c_str();
      msg += " failed: ";
      msg += strerror(result);
      m_debugger->sendUserMessage(
        msg.c_str(),
        DebugTransport::OutputLevelWarning
      );
    }
  }

  // Obviously don't log the auth token itself, but log whether or not we've
  // got one.
  VSDebugLogger::Log(
    VSDebugLogger::LogLevelInfo,
    "Client provided an auth token? %s",
    debuggerSessionAuthToken.empty() ? "NO" : "YES"
  );

  if (!startupDoc.empty()) {
    m_debugger->startDummyRequest(
      startupDoc,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  } else {
    m_debugger->startDummyRequest(
      emptyString,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  }

  DebuggerOptions options = {0};
  options.showDummyOnAsyncPause = showDummyOnAsyncPause;
  options.warnOnInterceptedFunctions = warnOnInterceptedFunctions;
  options.notifyOnBpCalibration = notifyOnBpCalibration;
  options.disableUniqueVarRef = disableUniqueVarRef;
  options.disableDummyPsPs = disableDummyPsPs;
  options.maxReturnedStringLength = maxReturnedStringLength;
  options.disableStdoutRedirection = disableStdoutRedirection;
  m_debugger->setDebuggerOptions(options);

  // Send the InitializedEvent to indicate to the front-end that we are up
  // and ready for breakpoint requests.
  folly::dynamic event = folly::dynamic::object;
  m_debugger->sendEventMessage(event, "initialized");

  // Re-send debugger capabilities in the launch / attach command response.
  // Note: while this is not documented in the protocol, VS Code uses this
  // to update capabilities after attaching in case they change after knowing
  // what version of the engine is launched.
  (*responseMsg)["body"] = getDebuggerCapabilities();

  // Completion of this command does not resume the target.
  return false;
}

}
}


bool LaunchAttachCommand::executeImpl(DebuggerSession* /*session*/,
                                      folly::dynamic* responseMsg) {
  folly::dynamic& message = getMessage();
  const folly::dynamic& args = tryGetObject(message, "arguments", s_emptyArgs);
  const std::string emptyString = std::string("");

  const auto& sandboxUser =
    tryGetString(args, "sandboxUser", emptyString);

  const auto& sandboxName =
    tryGetString(args, "sandboxName", "default");

  const auto& startupDoc =
    tryGetString(args, "startupDocumentPath", emptyString);

  bool displayStartupMsg =
    tryGetBool(args, "displayConsoleStartupMsg", true);

  bool showDummyOnAsyncPause =
     tryGetBool(args, "showDummyOnAsyncPause", false);

  bool warnOnInterceptedFunctions =
    tryGetBool(args, "warnOnInterceptedFunctions", false);

  bool notifyOnBpCalibration =
    tryGetBool(args, "notifyOnBpCalibration", false);

  bool disableUniqueVarRef =
    tryGetBool(args, "disableUniqueVarRef", false);

  bool disableDummyPsPs =
    tryGetBool(args, "disableDummyPsPs", false);

  bool disableStdoutRedirection =
    tryGetBool(args, "disableStdoutRedirection", false);

  const auto& logFilePath =
    tryGetString(args, "logFilePath", emptyString);

  const auto debuggerSessionAuthToken =
    tryGetString(args, "debuggerSessionAuthToken", emptyString);

  auto maxReturnedStringLength =
    tryGetInt(args, "maxReturnedStringLength", 32 * 1024);

  if (!logFilePath.empty()) {
    // Re-open logging using the file path specified by the client.
    int result = VSDebugLogger::InitializeLogging(logFilePath);
    if (result != 0) {
      std::string msg = "Opening log file ";
      msg += logFilePath.c_str();
      msg += " failed: ";
      msg += strerror(result);
      m_debugger->sendUserMessage(
        msg.c_str(),
        DebugTransport::OutputLevelWarning
      );
    }
  }

  // Obviously don't log the auth token itself, but log whether or not we've
  // got one.
  VSDebugLogger::Log(
    VSDebugLogger::LogLevelInfo,
    "Client provided an auth token? %s",
    debuggerSessionAuthToken.empty() ? "NO" : "YES"
  );

  if (!startupDoc.empty()) {
    m_debugger->startDummyRequest(
      startupDoc,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  } else {
    m_debugger->startDummyRequest(
      emptyString,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  }

  DebuggerOptions options = {0};
  options.showDummyOnAsyncPause = showDummyOnAsyncPause;
  options.warnOnInterceptedFunctions = warnOnInterceptedFunctions;
  options.notifyOnBpCalibration = notifyOnBpCalibration;
  options.disableUniqueVarRef = disableUniqueVarRef;
  options.disableDummyPsPs = disableDummyPsPs;
  options.maxReturnedStringLength = maxReturnedStringLength;
  options.disableStdoutRedirection = disableStdoutRedirection;
  m_debugger->setDebuggerOptions(options);

  // Send the InitializedEvent to indicate to the front-end that we are up
  // and ready for breakpoint requests.
  folly::dynamic event = folly::dynamic::object;
  m_debugger->sendEventMessage(event, "initialized");

  // Re-send debugger capabilities in the launch / attach command response.
  // Note: while this is not documented in the protocol, VS Code uses this
  // to update capabilities after attaching in case they change after knowing
  // what version of the engine is launched.
  (*responseMsg)["body"] = getDebuggerCapabilities();

  // Completion of this command does not resume the target.
  return false;
}

}
}


{
  folly::dynamic& message = getMessage();
  const folly::dynamic& args = tryGetObject(message, "arguments", s_emptyArgs);
  const std::string emptyString = std::string("");

  const auto& sandboxUser =
    tryGetString(args, "sandboxUser", emptyString);

  const auto& sandboxName =
    tryGetString(args, "sandboxName", "default");

  const auto& startupDoc =
    tryGetString(args, "startupDocumentPath", emptyString);

  bool displayStartupMsg =
    tryGetBool(args, "displayConsoleStartupMsg", true);

  bool showDummyOnAsyncPause =
     tryGetBool(args, "showDummyOnAsyncPause", false);

  bool warnOnInterceptedFunctions =
    tryGetBool(args, "warnOnInterceptedFunctions", false);

  bool notifyOnBpCalibration =
    tryGetBool(args, "notifyOnBpCalibration", false);

  bool disableUniqueVarRef =
    tryGetBool(args, "disableUniqueVarRef", false);

  bool disableDummyPsPs =
    tryGetBool(args, "disableDummyPsPs", false);

  bool disableStdoutRedirection =
    tryGetBool(args, "disableStdoutRedirection", false);

  const auto& logFilePath =
    tryGetString(args, "logFilePath", emptyString);

  const auto debuggerSessionAuthToken =
    tryGetString(args, "debuggerSessionAuthToken", emptyString);

  auto maxReturnedStringLength =
    tryGetInt(args, "maxReturnedStringLength", 32 * 1024);

  if (!logFilePath.empty()) {
    // Re-open logging using the file path specified by the client.
    int result = VSDebugLogger::InitializeLogging(logFilePath);
    if (result != 0) {
      std::string msg = "Opening log file ";
      msg += logFilePath.c_str();
      msg += " failed: ";
      msg += strerror(result);
      m_debugger->sendUserMessage(
        msg.c_str(),
        DebugTransport::OutputLevelWarning
      );
    }
  }

  // Obviously don't log the auth token itself, but log whether or not we've
  // got one.
  VSDebugLogger::Log(
    VSDebugLogger::LogLevelInfo,
    "Client provided an auth token? %s",
    debuggerSessionAuthToken.empty() ? "NO" : "YES"
  );

  if (!startupDoc.empty()) {
    m_debugger->startDummyRequest(
      startupDoc,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  } else {
    m_debugger->startDummyRequest(
      emptyString,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  }

  DebuggerOptions options = {0};
  options.showDummyOnAsyncPause = showDummyOnAsyncPause;
  options.warnOnInterceptedFunctions = warnOnInterceptedFunctions;
  options.notifyOnBpCalibration = notifyOnBpCalibration;
  options.disableUniqueVarRef = disableUniqueVarRef;
  options.disableDummyPsPs = disableDummyPsPs;
  options.maxReturnedStringLength = maxReturnedStringLength;
  options.disableStdoutRedirection = disableStdoutRedirection;
  m_debugger->setDebuggerOptions(options);

  // Send the InitializedEvent to indicate to the front-end that we are up
  // and ready for breakpoint requests.
  folly::dynamic event = folly::dynamic::object;
  m_debugger->sendEventMessage(event, "initialized");

  // Re-send debugger capabilities in the launch / attach command response.
  // Note: while this is not documented in the protocol, VS Code uses this
  // to update capabilities after attaching in case they change after knowing
  // what version of the engine is launched.
  (*responseMsg)["body"] = getDebuggerCapabilities();

  // Completion of this command does not resume the target.
  return false;
}

}
}


const auto debuggerSessionAuthToken =
    tryGetString(args, "debuggerSessionAuthToken", emptyString);

  auto maxReturnedStringLength =
    tryGetInt(args, "maxReturnedStringLength", 32 * 1024);

  if (!logFilePath.empty()) {
    // Re-open logging using the file path specified by the client.
    int result = VSDebugLogger::InitializeLogging(logFilePath);
    if (result != 0) {
      std::string msg = "Opening log file ";
      msg += logFilePath.c_str();
      msg += " failed: ";
      msg += strerror(result);
      m_debugger->sendUserMessage(
        msg.c_str(),
        DebugTransport::OutputLevelWarning
      );
    }
  }

  // Obviously don't log the auth token itself, but log whether or not we've
  // got one.
  VSDebugLogger::Log(
    VSDebugLogger::LogLevelInfo,
    "Client provided an auth token? %s",
    debuggerSessionAuthToken.empty() ? "NO" : "YES"
  );

  if (!startupDoc.empty()) {
    m_debugger->startDummyRequest(
      startupDoc,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  } else {
    m_debugger->startDummyRequest(
      emptyString,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  }

  DebuggerOptions options = {0};
  options.showDummyOnAsyncPause = showDummyOnAsyncPause;
  options.warnOnInterceptedFunctions = warnOnInterceptedFunctions;
  options.notifyOnBpCalibration = notifyOnBpCalibration;
  options.disableUniqueVarRef = disableUniqueVarRef;
  options.disableDummyPsPs = disableDummyPsPs;
  options.maxReturnedStringLength = maxReturnedStringLength;

/*
   +----------------------------------------------------------------------+
   | HipHop for PHP                                                       |
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
*/

#include "hphp/runtime/ext/vsdebug/debugger.h"
#include "hphp/runtime/ext/vsdebug/command.h"

namespace HPHP {
namespace VSDEBUG {

LaunchAttachCommand::LaunchAttachCommand(
  Debugger* debugger,
  folly::dynamic message
) : VSCommand(debugger, message) {
}

LaunchAttachCommand::~LaunchAttachCommand() {
}

bool LaunchAttachCommand::executeImpl(DebuggerSession* /*session*/,
                                      folly::dynamic* responseMsg) {
  folly::dynamic& message = getMessage();
  const folly::dynamic& args = tryGetObject(message, "arguments", s_emptyArgs);
  const std::string emptyString = std::string("");

  const auto& sandboxUser =
    tryGetString(args, "sandboxUser", emptyString);

  const auto& sandboxName =
    tryGetString(args, "sandboxName", "default");

  const auto& startupDoc =
    tryGetString(args, "startupDocumentPath", emptyString);

  bool displayStartupMsg =
    tryGetBool(args, "displayConsoleStartupMsg", true);

  bool showDummyOnAsyncPause =
     tryGetBool(args, "showDummyOnAsyncPause", false);

  bool warnOnInterceptedFunctions =
    tryGetBool(args, "warnOnInterceptedFunctions", false);

  bool notifyOnBpCalibration =
    tryGetBool(args, "notifyOnBpCalibration", false);

  bool disableUniqueVarRef =
    tryGetBool(args, "disableUniqueVarRef", false);

  bool disableDummyPsPs =
    tryGetBool(args, "disableDummyPsPs", false);

  bool disableStdoutRedirection =
    tryGetBool(args, "disableStdoutRedirection", false);

  const auto& logFilePath =
    tryGetString(args, "logFilePath", emptyString);

  options.disableStdoutRedirection = disableStdoutRedirection;
  m_debugger->setDebuggerOptions(options);

  // Send the InitializedEvent to indicate to the front-end that we are up
  // and ready for breakpoint requests.
  folly::dynamic event = folly::dynamic::object;
  m_debugger->sendEventMessage(event, "initialized");

  // Re-send debugger capabilities in the launch / attach command response.
  // Note: while this is not documented in the protocol, VS Code uses this
  // to update capabilities after attaching in case they change after knowing
  // what version of the engine is launched.
  (*responseMsg)["body"] = getDebuggerCapabilities();

  // Completion of this command does not resume the target.
  return false;
}

}
}


options.disableStdoutRedirection = disableStdoutRedirection;
  m_debugger->setDebuggerOptions(options);

  // Send the InitializedEvent to indicate to the front-end that we are up
  // and ready for breakpoint requests.
  folly::dynamic event = folly::dynamic::object;
  m_debugger->sendEventMessage(event, "initialized");

  // Re-send debugger capabilities in the launch / attach command response.
  // Note: while this is not documented in the protocol, VS Code uses this
  // to update capabilities after attaching in case they change after knowing
  // what version of the engine is launched.
  (*responseMsg)["body"] = getDebuggerCapabilities();

  // Completion of this command does not resume the target.
  return false;
}

/*
   +----------------------------------------------------------------------+
   | HipHop for PHP                                                       |
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
*/

#include "hphp/runtime/ext/vsdebug/debugger.h"
#include "hphp/runtime/ext/vsdebug/command.h"

namespace HPHP {
namespace VSDEBUG {

LaunchAttachCommand::LaunchAttachCommand(
  Debugger* debugger,
  folly::dynamic message
) : VSCommand(debugger, message) {
}

LaunchAttachCommand::~LaunchAttachCommand() {
}

bool LaunchAttachCommand::executeImpl(DebuggerSession* /*session*/,
                                      folly::dynamic* responseMsg) {
  folly::dynamic& message = getMessage();
  const folly::dynamic& args = tryGetObject(message, "arguments", s_emptyArgs);
  const std::string emptyString = std::string("");

  const auto& sandboxUser =
    tryGetString(args, "sandboxUser", emptyString);

  const auto& sandboxName =
    tryGetString(args, "sandboxName", "default");

  const auto& startupDoc =
    tryGetString(args, "startupDocumentPath", emptyString);

  bool displayStartupMsg =
    tryGetBool(args, "displayConsoleStartupMsg", true);

  bool showDummyOnAsyncPause =
     tryGetBool(args, "showDummyOnAsyncPause", false);

  bool warnOnInterceptedFunctions =
    tryGetBool(args, "warnOnInterceptedFunctions", false);

  bool notifyOnBpCalibration =
    tryGetBool(args, "notifyOnBpCalibration", false);

  bool disableUniqueVarRef =
    tryGetBool(args, "disableUniqueVarRef", false);

  bool disableDummyPsPs =
    tryGetBool(args, "disableDummyPsPs", false);

  bool disableStdoutRedirection =
    tryGetBool(args, "disableStdoutRedirection", false);

  const auto& logFilePath =
    tryGetString(args, "logFilePath", emptyString);

  const auto debuggerSessionAuthToken =
    tryGetString(args, "debuggerSessionAuthToken", emptyString);

  auto maxReturnedStringLength =
    tryGetInt(args, "maxReturnedStringLength", 32 * 1024);

  if (!logFilePath.empty()) {
    // Re-open logging using the file path specified by the client.
    int result = VSDebugLogger::InitializeLogging(logFilePath);
    if (result != 0) {
      std::string msg = "Opening log file ";
      msg += logFilePath.c_str();
      msg += " failed: ";
      msg += strerror(result);
      m_debugger->sendUserMessage(
        msg.c_str(),
        DebugTransport::OutputLevelWarning
      );
    }
  }

  // Obviously don't log the auth token itself, but log whether or not we've
  // got one.
  VSDebugLogger::Log(
    VSDebugLogger::LogLevelInfo,
    "Client provided an auth token? %s",
    debuggerSessionAuthToken.empty() ? "NO" : "YES"
  );

  if (!startupDoc.empty()) {
    m_debugger->startDummyRequest(
      startupDoc,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  } else {
    m_debugger->startDummyRequest(
      emptyString,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  }

  DebuggerOptions options = {0};
  options.showDummyOnAsyncPause = showDummyOnAsyncPause;
  options.warnOnInterceptedFunctions = warnOnInterceptedFunctions;
  options.notifyOnBpCalibration = notifyOnBpCalibration;
  options.disableUniqueVarRef = disableUniqueVarRef;
  options.disableDummyPsPs = disableDummyPsPs;
  options.maxReturnedStringLength = maxReturnedStringLength;


/*
   +----------------------------------------------------------------------+
   | HipHop for PHP                                                       |
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
*/

#include "hphp/runtime/ext/vsdebug/debugger.h"
#include "hphp/runtime/ext/vsdebug/command.h"

namespace HPHP {
namespace VSDEBUG {

LaunchAttachCommand::LaunchAttachCommand(
  Debugger* debugger,
  folly::dynamic message
) : VSCommand(debugger, message) {
}

LaunchAttachCommand::~LaunchAttachCommand() {
}

bool LaunchAttachCommand::executeImpl(DebuggerSession* /*session*/,
                                      folly::dynamic* responseMsg) {
  folly::dynamic& message = getMessage();
  const folly::dynamic& args = tryGetObject(message, "arguments",

  const std::string emptyString = std::string("");

  const auto& sandboxUser =
    tryGetString(args, "sandboxUser", emptyString);

  const auto& sandboxName =
    tryGetString(args, "sandboxName", "default");

  const auto& startupDoc =
    tryGetString(args, "startupDocumentPath", emptyString);

  bool displayStartupMsg =
    tryGetBool(args, "displayConsoleStartupMsg", true);

  bool showDummyOnAsyncPause =
     tryGetBool(args, "showDummyOnAsyncPause", false);

  bool warnOnInterceptedFunctions =
    tryGetBool(args, "warnOnInterceptedFunctions", false);

  bool notifyOnBpCalibration =
    tryGetBool(args, "notifyOnBpCalibration", false);

  bool disableUniqueVarRef =
    tryGetBool(args, "disableUniqueVarRef", false);

  bool disableDummyPsPs =
    tryGetBool(args, "disableDummyPsPs", false);

  bool disableStdoutRedirection =
    tryGetBool(args, "disableStdoutRedirection", false);

  const auto& logFilePath =
    tryGetString(args, "logFilePath", emptyString);

  const auto debuggerSessionAuthToken =
    tryGetString(args, "debuggerSessionAuthToken", emptyString);

  auto maxReturnedStringLength =
    tryGetInt(args, "maxReturnedStringLength", 32 * 1024);

  if (!logFilePath.empty()) {
    // Re-open logging using the file path specified by the client.
    int result = VSDebugLogger::InitializeLogging(logFilePath);
    if (result != 0) {
      std::string msg = "Opening log file ";
      msg += logFilePath.c_str();
      msg += " failed: ";
      msg += strerror(result);
      m_debugger->sendUserMessage(
        msg.c_str(),
        DebugTransport::OutputLevelWarning
      );
    }
  }

  // Obviously don't log the auth token itself, but log whether or not we've
  // got one.
  VSDebugLogger::Log(
    VSDebugLogger::LogLevelInfo,
    "Client provided an auth token? %s",
    debuggerSessionAuthToken.empty() ? "NO" : "YES"
  );

  if (!startupDoc.empty()) {
    m_debugger->startDummyRequest(
      startupDoc,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  } else {
    m_debugger->startDummyRequest(
      emptyString,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  }

  DebuggerOptions options = {0};
  options.showDummyOnAsyncPause = showDummyOnAsyncPause;
  options.warnOnInterceptedFunctions = warnOnInterceptedFunctions;
  options.notifyOnBpCalibration = notifyOnBpCalibration;
  options.disableUniqueVarRef = disableUniqueVarRef;
  options.disableDummyPsPs = disableDummyPsPs;
  options.maxReturnedStringLength = maxReturnedStringLength;
  options.disableStdoutRedirection = disableStdoutRedirection;
  m_debugger->setDebuggerOptions(options);

  // Send the InitializedEvent to indicate to the front-end that we are up
  // and ready for breakpoint requests.
  folly::dynamic event = folly::dynamic::object;
  m_debugger->sendEventMessage(event, "initialized");

  // Re-send debugger capabilities in the launch / attach command response.
  // Note: while this is not documented in the protocol, VS Code uses this
  // to update capabilities after attaching in case they change after knowing
  // what version of the engine is launched.
  (*responseMsg)["body"] = getDebuggerCapabilities();

  // Completion of this command does not resume the target.
  return false;
}

}
}


if (!startupDoc.empty()) {
    m_debugger->startDummyRequest(
      startupDoc,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  } else {
    m_debugger->startDummyRequest(
      emptyString,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  }

/*
   +----------------------------------------------------------------------+
   | HipHop for PHP                                                       |
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
*/

#include "hphp/runtime/ext/vsdebug/debugger.h"
#include "hphp/runtime/ext/vsdebug/command.h"

namespace HPHP {
namespace VSDEBUG {

LaunchAttachCommand::LaunchAttachCommand(
  Debugger* debugger,
  folly::dynamic message
) : VSCommand(debugger, message) {
}

LaunchAttachCommand::~LaunchAttachCommand() {
}

bool LaunchAttachCommand::executeImpl(DebuggerSession* /*session*/,
                                      folly::dynamic* responseMsg) {
  folly::dynamic& message = getMessage();
  const folly::dynamic& args = tryGetObject(message, "arguments", s_emptyArgs);
  const std::string emptyString = std::string("");

  const auto& sandboxUser =
    tryGetString(args, "sandboxUser", emptyString);

  const auto& sandboxName =
    tryGetString(args, "sandboxName", "default");

  const auto& startupDoc =
    tryGetString(args, "startupDocumentPath", emptyString);

  bool displayStartupMsg =
    tryGetBool(args, "displayConsoleStartupMsg", true);

  bool showDummyOnAsyncPause =
     tryGetBool(args, "showDummyOnAsyncPause", false);

  bool warnOnInterceptedFunctions =
    tryGetBool(args, "warnOnInterceptedFunctions", false);

  bool notifyOnBpCalibration =
    tryGetBool(args, "notifyOnBpCalibration", false);

  bool disableUniqueVarRef =
    tryGetBool(args, "disableUniqueVarRef", false);

  bool disableDummyPsPs =
    tryGetBool(args, "disableDummyPsPs", false);

  bool disableStdoutRedirection =
    tryGetBool(args, "disableStdoutRedirection", false);

  const auto& logFilePath =
    tryGetString(args, "logFilePath", emptyString);

  const auto debuggerSessionAuthToken =
    tryGetString(args, "debuggerSessionAuthToken", emptyString);

  auto maxReturnedStringLength =
    tryGetInt(args, "maxReturnedStringLength", 32 * 1024);

  if (!logFilePath.empty()) {
    // Re-open logging using the file path specified by the client.
    int result = VSDebugLogger::InitializeLogging(logFilePath);
    if (result != 0) {
      std::string msg = "Opening log file ";
      msg += logFilePath.c_str();
      msg += " failed: ";
      msg += strerror(result);
      m_debugger->sendUserMessage(
        msg.c_str(),
        DebugTransport::OutputLevelWarning
      );
    }
  }

  // Obviously don't log the auth token itself, but log whether or not we've
  // got one.
  VSDebugLogger::Log(
    VSDebugLogger::LogLevelInfo,
    "Client provided an auth token? %s",
    debuggerSessionAuthToken.empty() ? "NO" : "YES"
  );

  DebuggerOptions options = {0};
  options.showDummyOnAsyncPause = showDummyOnAsyncPause;
  options.warnOnInterceptedFunctions = warnOnInterceptedFunctions;
  options.notifyOnBpCalibration = notifyOnBpCalibration;
  options.disableUniqueVarRef = disableUniqueVarRef;
  options.disableDummyPsPs = disableDummyPsPs;
  options.maxReturnedStringLength = maxReturnedStringLength;
  options.disableStdoutRedirection = disableStdoutRedirection;
  m_debugger->setDebuggerOptions(options);

  // Send the InitializedEvent to indicate to the front-end that we are up
  // and ready for breakpoint requests.
  folly::dynamic event = folly::dynamic::object;
  m_debugger->sendEventMessage(event, "initialized");

  // Re-send debugger capabilities in the launch / attach command response.
  // Note: while this is not documented in the protocol, VS Code uses this
  // to update capabilities after attaching in case they change after knowing
  // what version of the engine is launched.
  (*responseMsg)["body"] = getDebuggerCapabilities();

  // Completion of this command does not resume the target.
  return false;
}

}
}


/*
   +----------------------------------------------------------------------+
   | HipHop for PHP                                                       |
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
*/

#include "hphp/runtime/ext/vsdebug/debugger.h"
#include "hphp/runtime/ext/vsdebug/command.h"

namespace HPHP {
namespace VSDEBUG {

LaunchAttachCommand::LaunchAttachCommand(
  Debugger* debugger,
  folly::dynamic message
) : VSCommand(debugger, message) {
}

LaunchAttachCommand::~LaunchAttachCommand() {
}

bool LaunchAttachCommand::executeImpl(DebuggerSession* /*session*/,
                                      folly::dynamic* responseMsg) {
  folly::dynamic& message = getMessage();
  const folly::dynamic& args = tryGetObject(message, "arguments", s_emptyArgs);
  const std::string emptyString = std::string("");

  const auto& sandboxUser =
    tryGetString(args, "sandboxUser", emptyString);

  const auto& sandboxName =
    tryGetString(args, "sandboxName", "default");

  const auto& startupDoc =
    tryGetString(args, "startupDocumentPath", emptyString);

  bool displayStartupMsg =
    tryGetBool(args, "displayConsoleStartupMsg", true);

  bool showDummyOnAsyncPause =
     tryGetBool(args, "showDummyOnAsyncPause", false);

  bool warnOnInterceptedFunctions =
    tryGetBool(args, "warnOnInterceptedFunctions", false);

  bool notifyOnBpCalibration =
    tryGetBool(args, "notifyOnBpCalibration", false);

  bool disableUniqueVarRef =
    tryGetBool(args, "disableUniqueVarRef", false);

  bool disableDummyPsPs =
    tryGetBool(args, "disableDummyPsPs", false);

  bool disableStdoutRedirection =
    tryGetBool(args, "disableStdoutRedirection", false);

  const auto& logFilePath =
    tryGetString(args, "logFilePath", emptyString);

  const auto debuggerSessionAuthToken =
    tryGetString(args, "debuggerSessionAuthToken", emptyString);

  auto maxReturnedStringLength =
    tryGetInt(args, "maxReturnedStringLength", 32 * 1024);

  if (!logFilePath.empty()) {
    // Re-open logging using the file path specified by the client.
    int result = VSDebugLogger::InitializeLogging(logFilePath);
    if (result != 0) {
      std::string msg = "Opening log file ";
      msg += logFilePath.c_str();
      msg += " failed: ";
      msg += strerror(result);
      m_debugger->sendUserMessage(
        msg.c_str(),
        DebugTransport::OutputLevelWarning
      );
    }
  }

  // Obviously don't log the auth token itself, but log whether or not we've
  // got one.
  VSDebugLogger::Log(
    VSDebugLogger::LogLevelInfo,
    "Client provided an auth token? %s",
    debuggerSessionAuthToken.empty() ? "NO" : "YES"
  );

  if (!startupDoc.empty()) {
    m_debugger->startDummyRequest(
      startupDoc,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  } else {
    m_debugger->startDummyRequest(
      emptyString,
      sandboxUser,
      sandboxName,
      debuggerSessionAuthToken,
      displayStartupMsg
    );
  }

  DebuggerOptions options = {0};
  options.showDummyOnAsyncPause = showDummyOnAsyncPause;
  options.warnOnInterceptedFunctions = warnOnInterceptedFunctions;
  options.notifyOnBpCalibration = notifyOnBpCalibration;
  options.disableUniqueVarRef = disableUniqueVarRef;
  options.disableDummyPsPs = disableDummyPsPs;
  options.maxReturnedStringLength = maxReturnedStringLength;
  options.disableStdoutRedirection = disableStdoutRedirection;
  m_debugger->setDebugger

Options(options);

  // Send the InitializedEvent to indicate to the front-end that we are up
  // and ready for breakpoint requests.
  folly::dynamic event = folly::dynamic::object;
  m_debugger->sendEventMessage(event, "initialized");

  // Re-send debugger capabilities in the launch / attach command response.
  // Note: while this is not documented in the protocol, VS Code uses this
  // to update capabilities after attaching in case they change after knowing
  // what version of the engine is launched.
  (*responseMsg)["body"] = getDebuggerCapabilities();

  // Completion of this command does not resume the target.
  return false;
}

}
}