// now #include the definition of std::complex<>
// and define the doublify() function.


#include <iostream>
#include <complex>
#ifdef _MSC_VER
#  include "vcl_msvc_warnings.h"
#endif


std::complex<double>
doublify(const std::complex<float> & z)
{
  return { std::real(z), std::imag(z) };
}


int
test_complex_main(int /*argc*/, char * /*argv*/[])
{
  const std::complex<double> dc1(1.1, 1.2);
  const std::complex<double> dc2(2.1, 2.2);
  const std::complex<float> fc1(1.1f, 1.2f);
  const std::complex<float> fc2(2.1f, 2.2f);

  std::cout << dc1 << " + " << dc2 << " = " << (dc1 + dc2) << std::endl
            << fc1 << " + " << fc2 << " = " << (fc1 + fc2) << std::endl;

  const std::complex<double> dc3(std::real(dc1), std::imag(dc2));
  const std::complex<float> fc3(std::real(fc1), std::imag(fc2));

  std::cout << dc3 << " / " << dc1 << " = " << dc3 / dc1 << std::endl
            << fc3 << " / " << fc1 << " = " << fc3 / fc1 << std::endl;

  std::cout << "polar representation of " << dc3 << " is [" << std::abs(dc3) << ',' << std::arg(dc3) << "]\n"
            << "going back: " << dc3 << " must be = " << std::polar(std::abs(dc3), std::arg(dc3)) << std::endl;
  const std::complex<float> fcsr3 = std::sqrt(fc3);
  std::cout << "sqrt(" << fc3 << ") is " << fcsr3 << ", so " << fcsr3 << " * " << fcsr3 << " = " << fcsr3 * fcsr3
            << std::endl;

  // Should also test form of complex stream input and output. The standard says:
  // [26.2.6.12] operator>> understands "u", "(u)" and  "(u,v)" where u, v are real.
  // [26.2.6.13] operator<< does f << '(' << x.real() << ',' << x.imag() << ')';
  // In particular, complex numbers written with operator<< can be read again with
  // operator>>.

  // complex should have a type called value_type;
  const std::complex<float>::value_type tmp = 1.0f;
  (void)tmp; // to avoid unused variable warnings.


  // Test the std::pow functions

  bool success = true;

  const std::complex<double> neg1(-1.0, 0.0);
  const std::complex<double> i(0.0, 1.0);
  std::complex<double> sqrt_neg1 = std::pow(neg1, 0.5);
  std::cout << "pow(" << neg1 << ",0.5) = " << sqrt_neg1 << " and should be (0,1)" << std::endl;
  double error = std::abs(sqrt_neg1 - i);
  // need to be careful of quiet NANs
  if (error < 0.0 || 1e-6 < error)
  {
    std::cout << "** FAILURE **\n";
    success = false;
  }

  const std::complex<double> half(0.5, 0.0);
  sqrt_neg1 = std::pow(neg1, half);
  std::cout << "pow(" << neg1 << ',' << half << ") = " << sqrt_neg1 << " and should be (0,1)" << std::endl;
  error = std::abs(sqrt_neg1 - i);
  if (error < 0.0 || 1e-6 < error)
  {
    std::cout << "** FAILURE **\n";
    success = false;
  }

  const std::complex<double> zero(0.0, 0.0);
  std::cout << "Implementation defines std::pow((0,0),(0,0)) = " << std::pow(zero, zero) << std::endl;

  {
    const std::complex<double> x(2, 3);
    const std::complex<double> xc = std::conj(x);
    std::cout << "Conjugate " << x << " = " << xc << '\n';
    if (xc != std::complex<double>(2, -3))
    {
      success = false;
    }
  }

  return success ? 0 : 1;
}
