#include <cassert>
#include <list>
#include <iostream>
using namespace std;

#include <random.h>
#include <randomtest.h>


template< typename R >
boolc randomtest::randomcontainer
( 
  list< typename R::Ttype > & lst,
  R & r, 
  uintc n,
  boolc zero,
  boolc one 
)
{
  for (uint i=0; i<n; ++i)
    lst.push_back(r());

  return domaintest(lst,r,zero,one);
}

template< typename R >
boolc randomtest::domaintest
(
  list< typename R::Ttype > & lst,
  R const & r, 
  boolc zero,
  boolc one 
)
{
  for 
  (
    typename list< typename R::Ttype >::iterator i = lst.begin();
    i!=lst.end(); i++ 
  )
  {
    if (randomgenerator::domain(*i,zero,one)==false)
      return false;
  }

  return true;
}

template< typename R >
boolc randomtest::testprintrandom
( 
  R & r, 
  uintc n,
  boolc zero,
  boolc one  
)
{
  list< typename R::Ttype > lst;

  bool res = randomtest::randomcontainer(lst,r,n,zero,one);

  for (
    typename list< typename R::Ttype >::iterator i = lst.begin();
    i!=lst.end(); i++ )
    { cout << *i << " "; }
  cout << endl << endl;

  cout << "Removing duplicates to look at sample space." << endl;

  lst.sort();
  lst.unique();

  for (
    typename list< typename R::Ttype >::iterator i = lst.begin();
    i!=lst.end(); i++ )
    { cout << *i << " "; }
  cout << endl << endl;

  assert(res);

  return res;
}

int randomtest::test01()
{
  cout << endl << "[0,1] interval, n=8" << endl; 
  random11<> r(8);
  return ! testprintrandom(r,30,true,true);
}

int randomtest::test02()
{
  cout << endl << "(0,1) interval, n=8" << endl;
  random00<> r(8);
  return ! testprintrandom(r,30,false,false);
}

int randomtest::test03()
{
  cout << endl << "[0,1) interval, n=8" << endl;
  random10<> r(8);
  return ! testprintrandom(r,30,true,false);
}

int randomtest::test04()
{
  cout << endl << "(0,1] interval, n=8" << endl;
  random01<> r(8);
  return ! testprintrandom(r,30,false,true);
}

int randomtest::test05()
{
  typedef point2<double> pt2;
  typedef point3<double> pt3;

  uint N=100;
  bool res=true;

  for (uint i=0; i<N; ++i)
  {
    pt2 p1 = randompoint<>().makepoint2();
//    cout << SHOW(p1) << endl;
    res &= randomgenerator::domain(p1);
  }

  for (uint i=0; i<N; ++i)
  {
    pt2 p1 = randompoint< random01<> >(random01<>(8)).makepoint2();
    res &= randomgenerator::domain(p1);
  }

  for (uint i=0; i<N; ++i)
  {
    pt2 p1 = randompoint< random10<> >(random10<>(8)).makepoint2();
    res &= randomgenerator::domain(p1);
  }

  for (uint i=0; i<N; ++i)
  {
    pt2 p1 = randompoint< random00<> >(random00<>(16)).makepoint2();
    res &= randomgenerator::domain(p1);
  }

  for (uint i=0; i<N; ++i)
  {
    pt3 p1 = randompoint<>().makepoint3();
//    cout << SHOW(p1) << endl;
    res &= randomgenerator::domain(p1);
  }
    
  return !res;
}

void randomtest::test06()
{
  uint count=10;
  cout << "Repeated list of random numbers each time this program called." << endl;
  cout << "Ouput " << count << " rand() numbers" << endl;
  for (uint i=0; i<count; ++i)
    cout << i << ": " << rand() << endl;
}

void randomtest::test07()
{
  randomgenerator().randomize_start();

  uint count=10;
  cout << "Different list of random numbers each time this program called." << endl;
  cout << "Ouput " << count << " rand() numbers" << endl;
  for (uint i=0; i<count; ++i)
    cout << i << ": " << rand() << endl;
}





