//---------------------------------------------------------------------------
// ŠNikolai V. Shokhirev, 2004-2008  <nikolai@shokhirev.com> http://www.shokhirev.com/nikolai.html
// Reduced demo version
//---------------------------------------------------------------------------
#include <string>
#include "GenTests.h"
#include "MathUtils.h"
#include "complex.h"

//---------------------------------------------------------------------------

using namespace std;

string MachepsTest()
{
  string ss = ">Macheps = ";
  real eps1, meps, eps = 1.0;
//  while ((1.0+eps)> 1.0){ meps = eps; eps /= 2.0; };
  do {meps = eps; eps /= 2.0; eps1 = eps + 1.0;} while (eps1 > 1.0);
  string s = ToString(meps);
  ss += s;

  eps = 1.0;
  do {meps = eps; eps /= 2.0;} while (eps > 0.0);
  s = ToString(meps);
  ss += "\n>MinDoube = ";
  ss += s;

  eps = 1.0;
  meps = 2097152.0;
  do {meps /= 2.0; eps /= 2.0;} while (eps > 0.0);
  s = ToString(meps);
  ss += "\n>SafeMinDoube = ";  // 1048576*MinDoube
  ss += s;
  return ss;
}

string ComplexTest()
{
  string s = "", ss = "Complex Test";
  bool fail = false;

  Complex c0;
  if (! Equal(c0, 0.0, 0.0)) { fail = true; s += " constructor 0 |"; };

  Complex c1(2.3);
  if (! Equal(c1, 2.3, 0.0)) { fail = true; s += " constructor 1 |"; };

  Complex c2(3.3,3.2);
  if (! Equal(c2, 3.3, 3.2)) { fail = true; s += " constructor 2 |"; };

  c0 = 2.2;
  if (! Equal(c0, 2.2, 0.0)) { fail = true; s += " real assignment |"; };

  c1.Im = 1.1; c0 = c1;  c2 = Complex(3.3, 3.2);
  if (! Equal(c0, 2.3, 1.1) || ! Equal(c2, 3.3, 3.2)) { fail = true; s += " complex assignment |"; };

  c0 = c1 = c2;
  if (! Equal(c0, c2) || !Equal(c1, c2)) { fail = true; s += " chain assignment |"; };

  c0 = c2 + 1.1;  c1 = 1.1 + c2;
  if (! Equal(c0, 4.4, 3.2) || !Equal(c1.Re, 4.4, 3.2)) { fail = true; s += "real addition |"; };

  c0 = c2 - 1.1;  c1 = 1.1 - c2;
  if (! Equal(c0, 2.2, 3.2) || !Equal(c1, -2.2, -3.2))  { fail = true; s += "real subtraction |"; };

  c0 = c2*2.0;  c1 = 2.0*c2;
  if (! Equal(c0, 6.6, 6.4) || !Equal(c1, 6.6, 6.4)) { fail = true; s += "real multiplication |"; };

  c0 = c0/2.0;  c1 = mod2(c1)/c1;
  if (! Equal(c0, c2) || !Equal(c1, 6.6, -6.4))  { fail = true; s += "real division |"; };

  c0 = -c2;  if (! Equal(-c0, c2) ) { fail = true; s += "unary minus |"; };

  c0 = +c2;  if (! Equal(+c0, c2) ) { fail = true; s += "unary plus |"; };

  c0 += c2; c1 = c2*2.0;
  if (! Equal(c0, c1) ) { fail = true; s += " += |"; };

  c0 = c2; c1 = c2*c0; c0 = c1/c2;
  if (! Equal(c0, c2) ) { fail = true; s += " complex * / |"; };

  c0 = Complex(2.2, 3.3);  c1 = Complex(4.4, 5.5);  c2 = c1 - c0;
  if (! Equal(c2, 2.2, 2.2) ) { fail = true; s += "complex addition/subtraction |"; };

  c0 = Complex(2.0, 3.0);  c1 = Complex(4.0, 5.0);  c2 = c1*c0;  c2 = c2/c1;
  if (! Equal(c0, c2) ) { fail = true; s += "complex multiplication/division |"; };

  if (fail) ss += " FAIL:" + s;
  else ss += " - OK";
  return ss;
}