/*******************************************************************************
+
+  LEDA 3.5
+
+  quadruple.h
+
+  This file is part of the LEDA research version (LEDA-R) that can be 
+  used free of charge in academic research and teaching. Any commercial
+  use of this software requires a license which is distributed by the
+  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
+  (fax +49 681 31104).
+
+  Copyright (c) 1991-1997  by  Max-Planck-Institut fuer Informatik
+  Im Stadtwald, 66123 Saarbruecken, Germany     
+  All rights reserved.
+ 
*******************************************************************************/
#ifndef _LEDA_QUADRUPLE_H
#define _LEDA_QUADRUPLE_H

#if !defined(LEDA_ROOT_INCL_ID)
#define LEDA_ROOT_INCL_ID 350103
#include <LEDA/REDEFINE_NAMES.h>
#endif

#define LEDA_PRINT_AND_READ

#include <LEDA/basic.h>


/*{\Manpage {quadruple} {A,B,C,D} {Quadruples} {p}}*/

/*{\Mdefinition
An instance |p| of type |\Mname| is a quadruple $(a,b,c,d)$ of variables  
of types $A$, $B$, $C$, and $D$, respectively. 

Related types are pairs,triples, and quadruples.
}*/


template <class A, class B, class C, class D>
class quadruple
{ A a;
  B b;
  C c;
  D d;

public:

/*{\Mcreation}*/ 

quadruple() {}
/*{\Mcreate creates an instance |\Mvar| of type |\Mname|. All components
are initialized to their default value.}*/

quadruple(const A& u, const B& v, const C& w, const D& x):
a(u), b(v), c(w), d(x)
{ }
/*{\Mcreate creates an instance |\Mvar| of type |\Mname| and initializes
it with the value $(u,v,w,x)$.}*/

// default copy constructor, assignment operator, and destructor work


/*{\Moperations 2 4}*/

const A&  first() const { return a;} 

      A& first() { return a;} 
/*{\Mop      returns the $A$-component of |\Mvar|. If |\Mvar| is a 
const-object the return type is $A$.}*/

const B&  second() const { return b;} 

      B& second() { return b;}
/*{\Mop      returns the $B$-component of |\Mvar|. If |\Mvar| is a 
const-object the return type is $B$.}*/

const C&  third() const { return c;}

      C& third() { return c;}
/*{\Mop      returns the $C$-component of |\Mvar|. If |\Mvar| is a 
const-object the return type is $C$.}*/

const D& fourth() const { return d;}

      D& fourth() { return d;}
/*{\Mop      returns the $D$-component of |\Mvar|. If |\Mvar| is a 
const-object the return type is $D$.}*/

LEDA_MEMORY(quadruple);

};


template <class A, class B, class C, class D>
void operator>>(istream& is,quadruple<A,B,C,D>& q)
{ is >> q.first();
  is >> q.second();
  is >> q.third();
  is >> q.fourth();
}

template <class A, class B, class C, class D>
void operator<<(ostream& os,const quadruple<A,B,C,D>& q)
{ os << q.first()  << " ";
  os << q.second() << " ";
  os << q.third()  << " ";
  os << q.fourth();
  }




template <class A, class B, class C, class D>
bool operator==(const quadruple<A,B,C,D>& p, const quadruple<A,B,C,D>& q)
{ return p.first() == q.first() && p.second() == q.second() &&
         p.third() == q.third() && p.fourth() == q.fourth();
}
/*{\Mbinopfunc equality test for quadruples. Each of the 
component types must have an equality operator. }*/



template <class A, class B, class C, class D>
int compare(const quadruple<A,B,C,D>& p, const quadruple<A,B,C,D>& q)
{ int s = compare(p.first(),q.first());
  if (s != 0) return s;
  s = compare(p.second(),q.second());
  if ( s!=0 ) return s;
  s = compare(p.third(),q.third());
  if ( s != 0 ) return s;
  return compare(p.fourth(),q.fourth());
}
/*{\Mfunc lexicographic ordering for quadruples. Each of the 
component types must have a compare function. }*/


template <class A, class B, class C, class D>
int Hash(const quadruple<A,B,C,D>& p)
{ return Hash(p.first()) & Hash(p.second()) & 
         Hash(p.third()) & Hash(p.fourth());
}
/*{\Mfunc hash function for quadruples. Each of the 
component types must have a Hash function.}*/


/*{\Mimplementation 
The obvious implementation is used.
}*/

/*{\Mexample

We customize quadruples and define a |h_array| for them.

\begin{verbatim}
#define prio() first()
#define inf()  second()
#define pq_item() third()
#define part_item() fourth()
typedef quadruple<int,int,int,int> my_qu;

my_qu q; 
my_qu q1(2,2,0,0);
q.prio() = 5;

h_array<my_qu,int> M;
M[my_qu(2,2,nil,nil)] = 5;
\end{verbatim}

}*/



#if LEDA_ROOT_INCL_ID == 350103
#undef LEDA_ROOT_INCL_ID
#include <LEDA/UNDEFINE_NAMES.h>
#endif
#endif

