#include <iostream>
#include <cstdlib>
#include <vector>
#include <ctime>

struct Data
{
   int key;
   int original_index;
};

bool compare_with_itself_called = false;
bool pointer_order_changed = false;

int compare(const void *p1, const void *p2)
{
   if(p1==p2)
   {
   	  compare_with_itself_called = true;
   	  return 0;
   }
   const Data *d1 = (const Data*)p1;
   const Data *d2 = (const Data*)p2;
   if(d1->key < d2->key)
     return -1;
   if(d2->key < d1->key)
     return 1;
   bool index_cond = d1->original_index<d2->original_index;
   bool ptr_cond = (p1<p2);
   if(index_cond!=ptr_cond)
   {
   	  pointer_order_changed = true;
   }
   return index_cond ? -1 : 1;
}

void outputArray(Data d[], unsigned n)
{
	for(unsigned i=0; i!=n; ++i)
	   std::cout << d[i].key << "@" << d[i].original_index << std::endl;
}

bool isStableSorted(const std::vector<Data>& d)
{
   size_t n = d.size();
   for(size_t i=1; i<n; ++i)
   {
      if(d[i-1].key==d[i].key &&
         d[i-1].original_index>d[i].original_index)
         return false;
   }
   return true;
}

int main()
{
   srand((unsigned)time(0));
   const unsigned NPASSES = 100000;
   unsigned nStableSorted = 0;
   for(unsigned pass=0; pass<NPASSES; ++pass)
   {
      unsigned N = rand()*1000/RAND_MAX+1;
      unsigned K = N/5+1;
      unsigned M = rand()*K/RAND_MAX+1;
      //
      std::vector<Data> d(N);
      for(unsigned i=0; i<N; ++i)
      {
         d[i].key = rand()*M/RAND_MAX+1;
         d[i].original_index = i;
      }
      //
      qsort(&(d[0]), N, sizeof(Data), compare);
      //
      if(isStableSorted(d))
         ++nStableSorted;
   }
   std::cout << "Total arrays sorted: " << NPASSES << std::endl;
   std::cout << "Stable-sorted arrays: " << nStableSorted << std::endl;
   std::cout << "compare_with_itself_called="
      << (compare_with_itself_called ? "true" : "false") << std::endl;
   std::cout << "pointer_order_changed="
      << (pointer_order_changed ? "true" : "false") << std::endl;
   return 0;
}

