//  File: array2.C
//
//  implementation of array class for testing sorting algorithms

#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
#include "array2.h"

// "Local" functions
//

static void CrashOnNULL(void *ptr, const char * mesg) ;

static void CrashOnNULL(void *ptr, const char * mesg) {
   if (ptr == NULL) {
      cerr << "CrashOnNULL: " << mesg << endl ;
      exit(1) ;
   }
}


// Default constructor initializes array to NULL
//
Array::Array() {

#ifndef NDEBUG
   cerr << "Array default constructor called, this =" << this << endl ;
#endif

   arr = NULL ;
   size = 0 ;
   seed = 0 ;
}


// Constructor initializes array to random values
//
Array::Array(int n, long seed /* = 0 */) {

#ifndef NDEBUG
   cerr << "Array alternate constructor called, this =" << this << endl ;
#endif

   if (n <= 0) {
      cerr << "Bad array size" << endl ;
      exit(1) ;
   }

   // if no seed given for random number generator, use time
   //
   if (seed == 0) seed = (long) time(NULL) ;
   srand48(seed) ;

   arr = new DATA[n] ;
   CrashOnNULL(arr, "Out of memory in alternate constructor") ;

   size = n ;
   Array::seed = seed ;

   for (int i = 0 ; i < size ; i++) {
      arr[i] = (DATA) drand48() ;
   }
}


// Copy constructor
//
Array::Array(const Array& B) {

#ifndef NDEBUG
   cerr << "Copy constructor called, this =" << this << endl ;
#endif

   *this = B ;  // use assignment to do the same thing
}


// Assignment
//
Array& Array::operator=(const Array& B) {

   // self assignment?
   if (this == &B) return *this ;

   seed = B.seed ;

   // empty array?
   if (B.size == 0) {
      size = 0 ;
      delete [] arr ;
      arr = NULL ;
      return *this ;
   }

   // Free old array?
   if (size != B.size) {
      size = B.size ;
      delete [] arr ;
      arr = new DATA[size] ;
      CrashOnNULL(arr, "Out of memory in assignment!") ;
   }

   for(int i = 0 ; i < size ; i++) {
      arr[i] = B.arr[i] ;
   }

   return *this ;
}


// Destructor
//
Array::~Array() {

#ifndef NDEBUG
   cerr << "Array destructor called, this = " << this << endl ;
#endif

   delete [] arr ;
}

void Array::print() const {

   for (int i = 0 ; i < size ; i++) {
      cout << setw(12) << arr[i] ;
      if (i % 5 == 4) cout <<endl ;
   }

   // need last CR?
   if (size % 5 != 0) {
      cout << endl ;
   }
}


bool Array::check() const {

   for (int i = 0 ; i < size-1 ; i++) {
      if (arr[i] > arr[i+1]) return false ;
   }
   return true ;
}


