// Emacs: -*- C++ -*-

#ifndef Coord_h_
#define Coord_h_

//
// $Log:	Coord.h,v $
// Revision 1.23  92/07/01  17:14:10  fischer
// Added Rob's simpler const constructor and operator= as inlines.
// 
// Revision 1.22  92/06/29  03:43:32  fischer
// Added real Coord &operator= code, uncommented the ~Coord(). Just in case.
// 
// Revision 1.21  92/06/28  05:18:00  fischer
// Made promote accept const NumericType args, made it const member function.
// 
// Revision 1.20  92/06/27  05:07:29  fischer
// Changed ouput operator << to use pass by ref for Coord so I 
// could get a look at what was happening in the (slightly busted)
// debugger.
// 
// Revision 1.19  92/06/17  15:22:29  thoth
// added input and string conversion operations.
// 
// Revision 1.18  92/06/16  13:57:19  thoth
// updated to follow new enum constant conventions
// removed operations that only make sense on integers
// 
// Revision 1.17  92/06/10  11:55:41  thoth
// updated some more, to reflect new conventions.
// 
// Revision 1.16  92/06/09  12:28:05  fischer
// Made most Coord operators non-member friends to get
// automatic type coercion.
// 
// Revision 1.15  92/06/08  02:52:38  fischer
// Simplified switch statements (removed Complex: and Rational:
// cases).  No extra break statements needed to be added (stylistic
// nit). Since Integer is the base type,  removed most calls to
// int(foo) $ int(bar)  where $ is some binary op,  replacing them
// with foo.value.i & bar.value.i.  This should result in substantial
// savings,  but will necessitate careful rewrite should a ``lower''
// type such as Char or Boolean be added to Coord.
// 
// Revision 1.14  92/06/02  01:45:52  fischer
// Made assignment operators const Coord&.  Removed 
// Removed !, &&, and ||.
// 
// Revision 1.13  92/05/27  07:46:40  fischer
// Added && and || as one arg friend functions, which is
// only way to preserve special semantics. Added bitwise
// compound assignment.  Changed bitwise operators to work
// between Coords, except for shift operators which now
// use signed ints.
// 
// Revision 1.13  1992/05/26  11:30:30  fischer
// Added more arithmetic and bitwise operators. Just a few to go.
//
// Revision 1.12  1992/05/24  11:44:53  fischer
// Added destructive assignment operations, pre- and post-
// increment and decrement.  Found << *will* work with gcc 2.0.
// None of this will work correctly with gcc 2.1 (overloading
// broken when application uses it).
//
// Revision 1.11  1992/05/22  07:13:50  fischer
// Got overloading to work by simple expedient of using math.ufl.edu
// version of g++:  gcc-2.0.
// Changed Coord arithmetic operators to assume result_type()
// is taking care of uninitialized Coord types (tag==None) via throw.
// Added default: to switches so Rob can rest easy about new
// NumericTypes.  Added *,/,+,%,-.  Lots more to go. Since we now
// have NumericType abstraction,  changed stuff like this->tag to
// this->type():  because these are inline functions, there should be little
// overhead, but we need to check with some timing tests.
// Changed Coord.val name to Coord.value name since I can never remember
// these damn c-style abbreviations.   .
//
// Revision 1.10  92/05/21  20:24:32  thoth
// switched to // comments for rcs log
// 
// Revision 1.9  92/05/21  15:10:55  thoth
// add addition operator.  Use of this operator
// causes the compiler to hang.
// declared some methods const (unmodifying).
// 
// Revision 1.8  92/05/21  12:05:23  thoth
// *** empty log message ***
// 
// Revision 1.7  92/05/21  08:07:58  fischer
// Started rework of CoordType to IA::NumericType
// so all classes can access.
// 
// Revision 1.6  92/05/20  06:29:29  fischer
// created a scheme to get around thoth's scheme:
// removed it.
// 
// Revision 1.5  92/05/18  15:15:42  thoth
// created a scheme to get around g++2.1's busted overloading
// and type conversion.
// 
// Revision 1.4  92/05/18  14:22:36  thoth
// modified conditional surrounding operator int and float.
// this gives readers a clue as to why they aren't available.
// 
// Revision 1.3  92/05/18  11:14:07  thoth
// minor frobs, added type converter,
// added tag retrieval method.
// 
// Revision 1.2  92/05/16  13:57:59  thoth
// added log goo
// 
// Revision 1.1  92/05/16  13:48:28  thoth
// Initial revision
//

// TO DO:: input <<
// TO DO:: check for self assignment special cases. 

#include <iostream.h>
#include "ia.h"

class Coord {
    NumericType	tag;
    union CoordValue {
	int	i;
	float	f;
    } value;


public:
    // constructors

    Coord() {tag=NONE;}
    Coord(int i)  {tag=INTEGER; value.i = i;}
    Coord(float f) {tag=REAL; value.f = f;}

    // Forsman sez gratuitous.
    //
    ~Coord(){}		
    Coord(const Coord& coordinate)	
    { this->tag = coordinate.tag; this->value = coordinate.value; }
    Coord &operator=(const Coord& coordinate)
    { this->tag = coordinate.tag; this->value = coordinate.value; return *this; }

    // Destructive arithmetic.
    
    Coord& operator++ ();
    Coord& operator-- ();

    operator int() const;
    operator float() const;

    // Some arithmetic operations.

    friend Coord operator+ (const Coord&, const Coord&);
    friend Coord operator* (const Coord&, const Coord&);
    friend Coord operator- (const Coord&);
    friend Coord operator- (const Coord&, const Coord&);
    friend Coord operator/ (const Coord&, const Coord&);

    //  It was decided that operations that only make sense on integers
    // would not be defined for Coords.  Coords may be implicitly converted
    // to integers just as efficiently as we can do it in a member function.

//     friend Coord operator% (const Coord&, const Coord&);
// 
//     // Bitwise functions.
// 
//     friend Coord operator~  (const Coord&);
//     friend Coord operator<< (const Coord&, unsigned int);
//     friend Coord operator>> (const Coord&, unsigned int);
//     friend Coord operator&  (const Coord&, const Coord&);
//     friend Coord operator^  (const Coord&, const Coord&);
//     friend Coord operator|  (const Coord&, const Coord&);

    // Comparisons.
    
    friend char operator <  (const Coord&, const Coord&);
    friend char operator <= (const Coord&, const Coord&);
    friend char operator == (const Coord&, const Coord&);
    friend char operator >= (const Coord&, const Coord&);
    friend char operator >  (const Coord&, const Coord&);
    friend char operator != (const Coord&, const Coord&);

    // Compound assignments

    const Coord& operator+=  (const Coord&);
    const Coord& operator*=  (const Coord&);
    const Coord& operator-=  (const Coord&);
    const Coord& operator/=  (const Coord&);
    const Coord& operator%=  (const Coord&);

    // however, implicit conversion to int does not help us for these functions

    const Coord& operator<<= (int);
    const Coord& operator>>= (int);

    const Coord& operator&=  (const Coord&);
    const Coord& operator^=  (const Coord&);
    const Coord& operator|=  (const Coord&);

    // Type functions.

    NumericType type() const {return this->tag;}

    Coord promote (const NumericType) const;

    friend ostream& operator<<(ostream&, Coord&);
    friend istream& operator>>(istream&, Coord&);
};

Coord atoCoord(const char *s);

#endif
