//
// LiDIA - a library for computational number theory
//   Copyright (c) 1995 by the LiDIA Group
//
// File        : ppair.h 
// Author      : Thomas Papanikolaou (TP), Thomas Pfahler (TPf)
// Last change : TPf, Jan 30 1996, adapted for use with pointer types
//

#ifndef LIDIA_PPAIR_H
#define LIDIA_PPAIR_H

#ifndef HEADBANGER


#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)
#include <LiDIA:lidia.h>
#else
#include <LiDIA/lidia.h>
#endif

template < class T1, class T2 > class ppair
{
  T1 *l;
  T2 r;

 public:

  ppair();
  ppair(T1 &pl, T2 &pr);
  ppair(const ppair < T1, T2 > &p);

  ~ppair();

  ppair < T1, T2 > &operator = (const ppair < T1, T2 > &p);


  const T1 & left() const
    {
      return *l;
    }

  const T2 & right() const
    {
      return r;
    }

  T1 & left()
    {
      return *l;
    }

  T2 & right()
    {
      return r;
    }

  void read(istream & in);
  void print(ostream & out) const;


 friend istream & operator >> (istream &in, ppair< T1, T2 > &p)
 { 
   p.read(in);
   return in;
 }

 friend ostream & operator << (ostream &out, const ppair< T1, T2 > &p)
 {
   p.print(out);
   return out;
 }

 int compare(const ppair < T1, T2 > &p) const;
 friend int compare(const ppair < T1, T2 > &p, const ppair < T1, T2 > &q)
 { return p.compare(q); }

  int operator == (const ppair < T1, T2 > &p) const;
  int operator != (const ppair < T1, T2 > &p) const;
  int operator > (const ppair < T1, T2 > &p) const;
  int operator >= (const ppair < T1, T2 > &p) const;
  int operator < (const ppair < T1, T2 > &p) const;
  int operator <= (const ppair < T1, T2 > &p) const;

 friend void swap(ppair < T1, T2 > &p, ppair < T1, T2 > &q);

};


/* begin implementation */

template < class T1, class T2 >
ppair< T1, T2 >::ppair()
{
	  l = new T1;
	  if (!l)
		lidia_error_handler("","out of memory");
	  // *l = 0;
	  r = 0;
}

template < class T1, class T2 >
ppair< T1, T2 >::ppair(T1 &pl, T2 &pr)
    {
      l = new T1;
	  if (!l)
		lidia_error_handler("","out of memory");
	  *l = pl;
      r = pr;
    }
	
template < class T1, class T2 >
ppair< T1, T2 >::ppair(const ppair < T1, T2 > &p)
    {
	  l = new T1;
	  if (!l)
	    lidia_error_handler("","out of memory");			  
      *l = *p.l;
      r = p.r;
    }
	
template < class T1, class T2 >
ppair< T1, T2 >::~ppair()
    {
	  delete l;
    }


template < class T1, class T2 >
ppair< T1, T2 > &
ppair< T1, T2 >::operator = (const ppair < T1, T2 > &p)
    {
      *l = *p.l;
      r = p.r;
      return *this;
    }


template < class T1, class T2 >
void ppair< T1, T2 >::read(istream & in)
  {
    debug_handler("pair", "read()");
    char c = 0;

    in >> c;
    if (c != '(')
       lidia_error_handler("pair", "read()::( expected");
    else
    {
	  in >> *l >> c;
	  if (c != ',')
	    lidia_error_handler("pair", "read()::, expected");
	  in >> r >> c;
	  while (c != ')')
	    in >> c;
    }
  } 

template < class T1, class T2 >
void ppair< T1, T2 >::print(ostream & out) const
  {
    debug_handler("pair", "print()");
    out << "( " << *l << " , " << r << " )";
  }


template < class T1, class T2 >
int ppair< T1, T2 >::compare(const ppair < T1, T2 > &p) const
  {
    int res = 0;
    if (*l > *p.l) res = 1;
    if (*l < *p.l) res = -1;

    if (res == 0)
      {
	if (r > p.r) res = 1;
	if (r < p.r) res = -1;
      }
    return res;
  }

template < class T1, class T2 >
int ppair< T1, T2 >::operator == (const ppair < T1, T2 > &p) const
    {
      int i = (*l == *p.l) && (r == p.r);
      return i;
    }
	
template < class T1, class T2 >
int ppair< T1, T2 >::operator != (const ppair < T1, T2 > &p) const
    {
      int i = (*l != *p.l) || (r != p.r);
      return i;
    }
	
template < class T1, class T2 >
int ppair< T1, T2 >::operator > (const ppair < T1, T2 > &p) const
    {
      int i = (*l > *p.l) || ((*l == *p.l) && (r > p.r));
      return i;
    }
	
template < class T1, class T2 >
int ppair< T1, T2 >::operator >= (const ppair < T1, T2 > &p) const
    {
      int i = (*l >= *p.l);
      return i;
    }
	
template < class T1, class T2 >
int ppair< T1, T2 >::operator < (const ppair < T1, T2 > &p) const
    {
      int i = (*l < *p.l) || ((*l == *p.l) && (r < p.r));
      return i;
    }
	
template < class T1, class T2 >
int ppair< T1, T2 >::operator <= (const ppair < T1, T2 > &p) const
    {
      int i = (*l <= *p.l);
      return i;
    }
	
template < class T1, class T2 >
void swap(ppair < T1, T2 > &p, ppair < T1, T2 > &q)
 {
   T1 *tmp_1 = p.l;
   p.l = q.l;
   q.l = tmp_1;

   T2 tmp_2 = p.r;
   p.r = q.r;
   q.r = tmp_2;
 }

#endif

#endif

