#include "rand.h"

//#include <stdlib>
#include <ctime>
#include <iostream>


#include "misc.h"


using namespace std;


// random mapping [0,n-1)
struct myrandom
{
   myrandom()  
   {
      srand( (unsigned int)time(NULL) );
   }

   int operator()(const int n) const { return rand() % n; }
};




void test01()
{
   const unsigned int asz=10;
   int a[asz] = { 1,3,5,7,9, 11,13,15,17,19 };

   random_shuffle(a,a+asz);
   copy(a,a+asz,ostream_iterator<int>(cout,"\n"));

   cout << endl << endl;

   myrandom r;
   random_shuffle(a,a+asz,r);
   copy(a,a+asz,ostream_iterator<int>(cout,"\n"));
}


void test02()
{
   randomnum<double> r;
   cout << SHOW(r()) << endl;


   vector<double> v;
   generate_n(back_inserter(v),20,r);

   copy(v.begin(),v.end(),ostream_iterator<double>(cout,"\n"));
}

class hat
{
public:

   template<class W>
   hat(W w) { cout << w << endl; }
};

// Attempt to convert from a temporary to a reference failed
template< class T>
T& fconst_cast(const T& t)
{
   return T(t);
}

void func01(hat& d)
{ cout << "*" << endl; }

//
// Investigating const_cast
//
void test03()
{
   hat h(30);
   const hat h2(5);

   func01( h );

   //
   // failed code: const_cast workes for named variables, not temporaries
   //
   //func01( const_cast<hat&>(hat(2)) );
   
   // This is what its designed for
   func01(const_cast<hat&>(h2));
}

//
// Look at reverse_copy
// and reverse
//
void test04()
{
    cout << "hello " << endl;

   int arr[3] = {1,2,3};


   const unsigned int n = sizeof(arr)/sizeof(int);
   copy(arr,arr+n, ostream_iterator<int>(cout," "));
   cout << endl;
   reverse_copy( arr,arr+n, ostream_iterator<int>(cout," "));
   cout << endl << endl;
  
   cout << "reverse the container" << endl;
   reverse(arr,arr+n);
   copy(arr,arr+n, ostream_iterator<int>(cout," "));
}

func( below15, x<15, x);


//
// <TODO>
// <TODO> Getting canned: why doesn't the below code compile?
// <TODO> Something to do with predicates? ...  @#@ 
// <TODO> 30th March 2002
//
template<class T>
class below_n
{
   T n;
   bool result;
public:
   
   below_n() {}
   below_n(const below_n<T>& x) { n=n.x; }

   below_n(T n_) : n(n_) {}
   bool& operator()(T x)  { result=(x<n); return result; }
};

// STL sux
// "Predicates are function that return a Boolean value...
// This rules out functions that modify their internal state
// when they are called."  page 121 "The Standard C++ Library"
// What are the consequences of this mentality? Better code or
// stupid library designers?  While they are saving us from
// ourselves, who is saving them from themselves? 



//
// Look at partition algorithm
//
void test05()
{
   below15<bool,bool&,int> c;
  
   cout << "testing function" << endl;
   cout << SHOW( c(20) ) << endl;
   cout << SHOW( c(10) ) << endl;

   cout << endl << endl;

   vector<int> v(20);
   for (unsigned int i=1; i<=v.size(); ++i)
      v[i-1]=i;
   vector<int> v2(v);
   vector<int> v3(v);

   myrandom r;
   random_shuffle(v.begin(),v.end(),r);
   cout << "before partition" << endl;
   copy(v.begin(),v.end(),ostream_iterator<int>(cout," "));
   cout << endl << endl;
   
   // Partition the container into 2 groups without respect 
   //   to order within these groups
   vector<int>::iterator j;
   j=partition(v.begin(),v.end(),c);
   cout << "after partition" << endl;
   copy(v.begin(),v.end(),ostream_iterator<int>(cout," "));
   cout << endl << endl;

   cout << "dereferencing the returned value of partition" << endl;
   cout << *j << endl;
   cout << endl << endl;

   cout << "before stable partition" << endl;
   random_shuffle(v2.begin(),v2.end(),r);
   copy(v2.begin(),v2.end(),ostream_iterator<int>(cout," "));
   cout << endl << endl;

   // Preserve the order with stable partition
   vector<int>::iterator k;
   k=stable_partition(v2.begin(),v2.end(),below15<bool,bool&,int>());
   cout << "after stable_partition" << endl;
   copy(v2.begin(),v2.end(),ostream_iterator<int>(cout," "));

   cout << endl << endl;
   cout << "dereferencing the returned value of stable_partition" << endl;
   cout << *k << endl;

   cout << endl << endl;
   cout << "using a configurable partition: set up in constructor" << endl;

   cout << "below_n(T n_)" << endl;
   random_shuffle(v3.begin(),v3.end(),r);
   cout << "before stable partition" << endl;
   copy(v3.begin(),v3.end(),ostream_iterator<int>(cout," "));
   cout << endl;
  
   below_n<int> w(7);
   cout << w(12) << endl;
   vector<int>::iterator k2;
   k2=stable_sort(v3.begin(),v3.end(),w);
   //k2=stable_sort(v3.begin(),v3.end(),below_n<int>(7));
/*
   cout << "after stable_partition" << endl;
   copy(v3.begin(),v3.end(),ostream_iterator<int>(cout," "));
   cout << endl;
   cout << "dereferencing the returned value of stable_partition" << endl;
   cout << *k2 << endl;
*/
}



int main()
{
   test05();

   return 0;
}


