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

/*
        Copyright 1993, Center for Computer Vision and Visualization,
        University of Florida.  All rights reserved.

// $Log: Point.h.m4,v $
// Revision 2.15  1993/11/16  13:27:10  thoth
// Pointcmp is now pointcmp
//
// Revision 2.14  1993/09/15  12:26:01  thoth
// Point is now a template with specializations only.
//
// Revision 2.13  93/05/26  16:59:41  rjj
// Added copyright notice
// 
// Revision 2.12  93/04/29  21:51:17  rjj
// Added missing  const  for  POINT op NUMBER.  See change in defines.m4 also.
// 
// Revision 2.11  93/04/06  22:25:39  rjj
// Removed const from "const int" and "const double"
// Changed bitwise unsigned parameters to int
// removed backwards compability with IntPoint and FloatPoint
// 
// Revision 2.10  93/04/05  23:00:56  rjj
// Many changes:
//   member size renamed to dimen
//   member dimensions() renamed as dim()
//   postfix members ++ and -- added
//   operator() changed into member derange() and extended with array version
//   member infimum() rename to inf()
//   member supremum() renamed to sup()
//   all references to IntPoint changed to IA_IntPoint
//   all references to FloatPoint changed to IA_FloatPoint
//   change to map IA_IntPoint to IntPoint now does the reverse
//   change to map IA_FloatPoint to FloatPoint now does the reverse
//   file reorganized to group related members as I saw fit
//   in general the interface as been mutated into the interface
//     reflected by newpoint, which spans Point.h, ArithPoint.h
//     LatticePoint.h, BitwisePoint.h and of course
//     IntPoint.h and FloatPoint.h
// 
// Revision 2.9  92/12/11  01:11:57  rjj
// Modified to support the IA_ prefix naming convention.
// Also put #ifdef IA_PRII around the #pragma stamt
// 
// Revision 2.8  92/09/02  14:50:44  rjj
// Corrected renameing of min to infimum and max to supremum
// 
// Revision 2.7  92/09/01  20:45:29  rjj
// Added support to ensure float op IntPoint and IntPoint op float
//  yield FloatPoint.
// 
// Revision 2.6  92/08/28  11:55:11  jnw
// Changed relation functions with POINT_TYPE& and float args
// to have POINT_TYPE& and double args to match current .C code
// 
// Revision 2.5  92/08/27  12:11:27  jnw
// Added C style comments around Log Messages to fixx gcc-cpp bug
// 
// Revision 2.4  92/08/23  13:35:47  thoth
// CFrontified
// throw changed to ia_throw.
// didn't hint to inline for loop stuff any more (braindead compiler).
// fixed const pass-by-value problem.
// 
// 

*/

ifdef(`FLOATPOINT', `
#ifndef IA_FloatPoint_h_
#define IA_FloatPoint_h_
')

ifdef(`INTPOINT', `
#ifndef IA_IntPoint_h_
#define IA_IntPoint_h_
')

#include "ia.h"

#ifdef IA_PRII
#pragma interface
#endif

#define SUPPRESS_INCLUDE
#include "Point.h"
#undef SUPPRESS_INCLUDE

ifdef(`FLOATPOINT', `#include "IntPoint.h"')


class POINT_TYPE {
    
  protected:  
    unsigned dimen;
    TYPE *coordinates;
    
  public:
    ////////////////////////////////////////////////////////////
    // C O N S T R U C T O R S
    ////////////////////////////////////////////////////////////
    
    POINT (const POINT_TYPE&);

    POINT () {coordinates = 0; dimen = 0; }
    
    POINT (TYPE c0) {
	coordinates = new TYPE[dimen = 1];
	coordinates[0] =  c0;
    }
    
    POINT (TYPE c0, TYPE c1) {
	coordinates = new TYPE[dimen = 2];
	coordinates[0] = c0;
	coordinates[1] = c1;
    }
    
    POINT (TYPE c0, TYPE c1, TYPE c2) {
	coordinates = new TYPE[dimen = 3];
	coordinates[0] = c0;
	coordinates[1] = c1;
	coordinates[2] = c2;
    }
    
    POINT (TYPE c0, TYPE c1, TYPE c2, TYPE c3) {
	coordinates = new TYPE[dimen = 4];
	coordinates[0] = c0;
	coordinates[1] = c1;
	coordinates[2] = c2;
	coordinates[3] = c3;
    }
    
    POINT (TYPE c0, TYPE c1, TYPE c2, TYPE c3, TYPE c4) {
	coordinates = new TYPE[dimen = 5];
	coordinates[0] = c0;
	coordinates[1] = c1;
	coordinates[2] = c2;
	coordinates[3] = c3;
	coordinates[4] = c4;
    }

ifdef(`FLOATPOINT',`
//  FloatPoint includes IntPoint.h so we can have a constructor from
//  IA_IntPoint to IA_FloatPoint: this gives us all
//  IA_FloatPoint/IA_IntPoint  operations for free.

    POINT (const IPOINT &ipt);
')

    POINT (TYPE *, unsigned, int =0);


    // Index-derangement functions.
    POINT_TYPE    derange (unsigned) const;
    POINT_TYPE    derange (unsigned, unsigned) const;
    POINT_TYPE    derange (unsigned, unsigned, unsigned) const;
    POINT_TYPE    derange (unsigned, unsigned, unsigned, unsigned) const;
    POINT_TYPE    derange (unsigned, unsigned, unsigned,
			   unsigned, unsigned) const;

    // Index-derangement, indices given by an array
    POINT_TYPE    derange (unsigned *, const unsigned) const;

    friend POINT_TYPE    extend_to_point (TYPE, unsigned);
    
    friend POINT_TYPE    concat   (const POINT_TYPE&, const POINT_TYPE&);
    friend POINT_TYPE    concat   (const POINT_TYPE&, TYPE);
    friend POINT_TYPE    concat   (TYPE, const POINT_TYPE&);

    friend POINT_TYPE    cdr      (const POINT_TYPE&, int =1);


    // The destructor for this class
    ~POINT () { delete[] coordinates; }  // OK even if coordinates NULL.


    ////////////////////////////////////////////////////////////
    // M I S C    O P E R A T I O N S
    ////////////////////////////////////////////////////////////

    POINT_TYPE& operator = (const POINT_TYPE&);

    unsigned            dim () const { return dimen; }

    friend POINT_TYPE	inf    (const POINT_TYPE&, const POINT_TYPE&);
    friend TYPE		min    (const POINT_TYPE&);
    friend POINT_TYPE	sup    (const POINT_TYPE&, const POINT_TYPE&);
    friend TYPE		max    (const POINT_TYPE&);

    friend ostream& operator << (ostream&, const POINT_TYPE&);


    ////////////////////////////////////////////////////////////
    // I N D E X I N G    O P E R A T I O N S
    ////////////////////////////////////////////////////////////

    TYPE&      operator[] (unsigned i)       { return coordinates[i]; }
    const TYPE operator[] (unsigned i) const { return coordinates[i]; }


    ////////////////////////////////////////////////////////////
    // A R I T H M E T I C   O P E R A T I O N S
    ////////////////////////////////////////////////////////////

    POINT_TYPE&   operator +=  (const POINT_TYPE&);
    POINT_TYPE&   operator -=  (const POINT_TYPE&);
    POINT_TYPE&   operator *=  (const POINT_TYPE&);
    POINT_TYPE&   operator /=  (const POINT_TYPE&);

    POINT_TYPE&   operator +=  (TYPE);
    POINT_TYPE&   operator -=  (TYPE);
    POINT_TYPE&   operator *=  (TYPE);
    POINT_TYPE&   operator /=  (TYPE);
    
    POINT_TYPE    operator +  (const POINT_TYPE&) const;
    POINT_TYPE    operator -  (const POINT_TYPE&) const;
    POINT_TYPE    operator *  (const POINT_TYPE&) const;
    POINT_TYPE    operator /  (const POINT_TYPE&) const;
    
    POINT_TYPE    operator +  (TYPE) const;
    POINT_TYPE    operator -  (TYPE) const;
    POINT_TYPE    operator *  (TYPE) const;
    POINT_TYPE    operator /  (TYPE) const;
    
    friend POINT_TYPE    operator +  (TYPE, const POINT_TYPE&);
    friend POINT_TYPE    operator -  (TYPE, const POINT_TYPE&);
    friend POINT_TYPE    operator *  (TYPE, const POINT_TYPE&);
    friend POINT_TYPE    operator /  (TYPE, const POINT_TYPE&);

ifdef(`FLOATPOINT',`
//  Ensure that float args yield IA_FloatPoint answers.
    friend POINT_TYPE    operator +  (const IPOINT&, TYPE);
    friend POINT_TYPE    operator -  (const IPOINT&, TYPE);
    friend POINT_TYPE    operator *  (const IPOINT&, TYPE);
    friend POINT_TYPE    operator /  (const IPOINT&, TYPE);

    friend POINT_TYPE    operator +  (TYPE, const IPOINT&);
    friend POINT_TYPE    operator -  (TYPE, const IPOINT&);
    friend POINT_TYPE    operator *  (TYPE, const IPOINT&);
    friend POINT_TYPE    operator /  (TYPE, const IPOINT&);
')


    POINT_TYPE    operator -   () const;

    // Prefix operators
    POINT_TYPE&   operator ++  ();
    POINT_TYPE&   operator --  ();

    // Postfix operators
    POINT_TYPE    operator ++ (int);
    POINT_TYPE    operator -- (int);

    double   enorm() const;   // Cartesian distance

ifdef(`FLOATPOINT',`
    friend POINT_TYPE aint  (POINT_TYPE);
    friend POINT_TYPE anint (POINT_TYPE);
    friend POINT_TYPE ceil  (POINT_TYPE);
    friend POINT_TYPE floor (POINT_TYPE);
    friend POINT_TYPE rint  (POINT_TYPE);

    friend IPOINT   irint (const POINT_TYPE&);
    friend IPOINT   nint  (const POINT_TYPE&);
    friend IPOINT   trunc (const POINT_TYPE&);
')



    ////////////////////////////////////////////////////////////
    // L A T T I C E   O P E R A T I O N S
    ////////////////////////////////////////////////////////////

    int    operator <   (const POINT_TYPE&) const;
    int    operator <=  (const POINT_TYPE&) const;
    int    operator >   (const POINT_TYPE&) const;
    int    operator >=  (const POINT_TYPE&) const;
    int    operator ==  (const POINT_TYPE&) const;
    int    operator !=  (const POINT_TYPE&) const;

    int    operator <   (TYPE) const;
    int    operator <=  (TYPE) const;
    int    operator >   (TYPE) const;
    int    operator >=  (TYPE) const;
    int    operator ==  (TYPE) const;
    int    operator !=  (TYPE) const;

    friend  int    operator <   (TYPE, const POINT_TYPE&);
    friend  int    operator <=  (TYPE, const POINT_TYPE&);
    friend  int    operator >   (TYPE, const POINT_TYPE&);
    friend  int    operator >=  (TYPE, const POINT_TYPE&);
    friend  int    operator ==  (TYPE, const POINT_TYPE&);
    friend  int    operator !=  (TYPE, const POINT_TYPE&);

ifdef(`INTPOINT',`
    // Ensure that IntPoints and float arguments are compared
    // without rounding to int issues.
    int    operator <   (double) const;
    int    operator <=  (double) const;
    int    operator >   (double) const;
    int    operator >=  (double) const;
    int    operator ==  (double) const;
    int    operator !=  (double) const;

    friend  int    operator <   (double, const POINT_TYPE&);
    friend  int    operator <=  (double, const POINT_TYPE&);
    friend  int    operator >   (double, const POINT_TYPE&);
    friend  int    operator >=  (double, const POINT_TYPE&);
    friend  int    operator ==  (double, const POINT_TYPE&);
    friend  int    operator !=  (double, const POINT_TYPE&);
')

    friend  int    pointcmp (const POINT_TYPE&, const POINT_TYPE&);


ifdef(`INTPOINT',`
    ////////////////////////////////////////////////////////////
    // B I T W I S E   O P E R A T I O N S
    ////////////////////////////////////////////////////////////

    POINT_TYPE    operator ~  () const;

    POINT_TYPE&   operator %=  (const POINT_TYPE&);
    POINT_TYPE&   operator <<= (const POINT_TYPE&);
    POINT_TYPE&   operator >>= (const POINT_TYPE&);
    POINT_TYPE&   operator &=  (const POINT_TYPE&);
    POINT_TYPE&   operator ^=  (const POINT_TYPE&);
    POINT_TYPE&   operator |=  (const POINT_TYPE&);

    POINT_TYPE&   operator %=  (int);
    POINT_TYPE&   operator <<= (int);
    POINT_TYPE&   operator >>= (int);
    POINT_TYPE&   operator &=  (int);
    POINT_TYPE&   operator ^=  (int);
    POINT_TYPE&   operator |=  (int);

    POINT_TYPE    operator %  (const POINT_TYPE&) const;
    POINT_TYPE    operator << (const POINT_TYPE&) const;
    POINT_TYPE    operator >> (const POINT_TYPE&) const;
    POINT_TYPE    operator &  (const POINT_TYPE&) const;
    POINT_TYPE    operator ^  (const POINT_TYPE&) const;
    POINT_TYPE    operator |  (const POINT_TYPE&) const;

    POINT_TYPE    operator %  (int) const;
    POINT_TYPE    operator << (int) const;
    POINT_TYPE    operator >> (int) const;
    POINT_TYPE    operator &  (int) const;
    POINT_TYPE    operator ^  (int) const;
    POINT_TYPE    operator |  (int) const;

    friend POINT_TYPE    operator %  (int, const POINT_TYPE&);
    friend POINT_TYPE    operator << (int, const POINT_TYPE&);
    friend POINT_TYPE    operator >> (int, const POINT_TYPE&);
    friend POINT_TYPE    operator &  (int, const POINT_TYPE&);
    friend POINT_TYPE    operator ^  (int, const POINT_TYPE&);
    friend POINT_TYPE    operator |  (int, const POINT_TYPE&);
')

};

typedef POINT_TYPE
ifdef(`INTPOINT', `IA_IntPoint')
ifdef(`FLOATPOINT', `IA_FloatPoint')
    ;



#endif
