head     2.7;
branch   ;
access   ;
symbols  ;
locks    ; strict;
comment  @// @;


2.7
date     92.08.20.21.59.10;  author rjj;  state Exp;
branches ;
next     2.6;

2.6
date     92.07.31.02.46.19;  author fischer;  state Exp;
branches ;
next     2.5;

2.5
date     92.07.29.23.45.24;  author fischer;  state Exp;
branches ;
next     2.4;

2.4
date     92.07.29.23.41.06;  author fischer;  state Exp;
branches ;
next     2.3;

2.3
date     92.07.29.03.21.06;  author fischer;  state Exp;
branches ;
next     2.2;

2.2
date     92.07.28.07.06.44;  author fischer;  state Exp;
branches ;
next     2.1;

2.1
date     92.07.27.06.24.10;  author fischer;  state Exp;
branches ;
next     2.0;

2.0
date     92.07.19.05.24.43;  author fischer;  state Exp;
branches ;
next     ;


desc
@Changed from cpp #defines to m4 defines()
@


2.7
log
@Changed all calls to throw(,,) to be calls to ia_throw(,,).
@
text
@// Emacs: -*- C++ -*-

static char rcsid[] = "$Id: Point.cc.m4,v 2.6 92/07/31 02:46:19 fischer Exp Locker: rjj $";

// $Log:	Point.cc.m4,v $
// Revision 2.6  92/07/31  02:46:19  fischer
// Fixed rscid typo.
// 
// Revision 2.5  92/07/29  23:45:24  fischer
// Fixed bad rcsid string marker.
// 
// Revision 2.4  92/07/29  23:41:06  fischer
// Changed relational operators to return int, Pointcmp as well.
// 
// Revision 2.3  92/07/29  03:21:06  fischer
// Lost pointcmp code between rev 2.0 and 2.1 -- reinserted it.
// 
// Revision 2.2  92/07/28  07:06:44  fischer
// removed max_dimensions static constant from Point classes.
// removed many checks for zero-length points, now that we 
// know "new foo[0]" gives us a pointer to one "foo" that can
// be safely deleted.  Did some more loop unrolling in functions
// like min.  A min-based test program showed 6% speedup 
// with g++ -O flag.
// 
// Revision 2.1  92/07/27  06:24:10  fischer
// fixed problem with nint/rint/trunc pointer.
// optimized constructors via loop unrolling.
// added min/max as binary (point,point) and
// unary (point) functions.
// 
// Revision 2.0  92/07/19  05:24:43  fischer
// Changed from cpp #defines to m4 defines().
// 
//
// Revision 1.6  92/07/18  04:57:08  fischer
// Added Pointcmp and (for FloatPoint) the rint(3M) family
// of math functions.
// 
// Revision 1.5  92/07/17  16:44:19  thoth
// copy constructor was missing.
// needed vector constructor to simplify some code
// 
// Revision 1.4  92/07/17  03:02:18  fischer
// Extended cdr to Rob's specifications.
// 
// Revision 1.3  92/07/17  01:24:42  fischer
// Added concat, derangement, cdr, enorm, unary -, ~, ++ and --.
// 
// Revision 1.2  92/07/16  18:46:07  fischer
// changed const {int,float} -> {int,float}
// 
// Revision 1.1  92/07/16  18:23:02  fischer
// Initial revision
// 
// 

#include <math.h>
ifdef(`INTPOINT', `#include "IntPoint.h"')
ifdef(`FLOATPOINT', `#include "FloatPoint.h"')


POINT_TYPE extend_to_point (TYPE initial_value, unsigned length) {
    POINT_TYPE pt;

    pt.coordinates = new TYPE[pt.size = length];

#ifdef NO_LOOP_UNROLLING
    for (unsigned i = 0; i < length; i++)
	pt.coordinates[i] = initial_value;
#else
    switch (pt.size) {
    case 5: pt.coordinates[4] = initial_value;
    case 4: pt.coordinates[3] = initial_value;
    case 3: pt.coordinates[2] = initial_value;
    case 2: pt.coordinates[1] = initial_value;
    case 1: pt.coordinates[0] = initial_value;
    case 0: break;
    default:
	for (unsigned i = 0; i < length; i++)
	    pt.coordinates[i] = initial_value;
    }
#endif    
    return pt;
}


POINT_TYPE::POINT_TYPE (const POINT_TYPE &ip)
{

// new TYPE[0] creates a pointer to one TYPE; we never use it.
// This is to keep from having to do "if (size == 0) ..." everywhere.
// The destructor will delete it, though.
    
    this->coordinates = new TYPE[this->size = ip.size];

#ifdef NO_LOOP_UNROLLING    
    for (unsigned i=0; i<this->size; i++)
	this->coordinates[i] = ip.coordinates[i];
#else
    switch (this->size) {
    case 5: this->coordinates[4] = ip.coordinates[4];
    case 4: this->coordinates[3] = ip.coordinates[3];
    case 3: this->coordinates[2] = ip.coordinates[2];
    case 2: this->coordinates[1] = ip.coordinates[1];
    case 1: this->coordinates[0] = ip.coordinates[0];
    case 0: break;
    default:
	for (unsigned i=0; i<this->size; i++)
	    this->coordinates[i] = ip.coordinates[i];
    }
#endif
}

POINT_TYPE::POINT_TYPE (TYPE *vec, unsigned length, int giveaway=0)
{
    this->size=length;
    if (giveaway) {
	this->coordinates = vec;
	return;
    }
    
    this->coordinates = new TYPE[this->size];
    
#ifdef NO_LOOP_UNROLLING    
    for (unsigned length=0; length<this->size; length++)
	this->coordinates[length] = vec[length];
#else	
    switch (this->size) {
    case 5: this->coordinates[4] = vec[4];
    case 4: this->coordinates[3] = vec[3];
    case 3: this->coordinates[2] = vec[2];
    case 2: this->coordinates[1] = vec[1];
    case 1: this->coordinates[0] = vec[0];
    case 0: break;
    default:
	for (unsigned length=0; length<this->size; length++)
		this->coordinates[length] = vec[length];
    }
#endif
}


POINT_TYPE &POINT_TYPE::operator = (const POINT_TYPE &point)
{
    // return directly when self-assignment (not sure the if is worth it in general)

    if (this == &point)
	return *this;

    // We need to deallocate/reallocate if differing sizes.
    
    if (point.size != this->size) {
        delete[] this->coordinates;
        this->coordinates = new TYPE[this->size = point.size];
    }

#ifdef NO_LOOP_UNROLLING
    for (unsigned i = 0; i < this->size; i++)
	this->coordinates[i] = point.coordinates[i];
#else
    switch (this->size) {
    case 5: this->coordinates[4] = point.coordinates[4];
    case 4: this->coordinates[3] = point.coordinates[3];
    case 3: this->coordinates[2] = point.coordinates[2];
    case 2: this->coordinates[1] = point.coordinates[1];
    case 1: this->coordinates[0] = point.coordinates[0];
    case 0: break;
    default:
	for (unsigned i = 0; i < this->size; i++)
	    this->coordinates[i] = point.coordinates[i];
    }
#endif
    return *this;
}

ostream &operator << (ostream &stream, const POINT_TYPE& point)
{
    int last_index = point.size - 1;
    stream << "<";
    for  ( int i = 0; i < last_index; ++i ) {
	stream << point.coordinates[i] << " ";
    }
    if ( point.size > 0 ) {
	stream << point.coordinates[last_index];
    };
    stream << ">";
    return stream;
}

COMPOUND_ARITH_ASSIGN_POINT(+)
COMPOUND_ARITH_ASSIGN_POINT(-)
COMPOUND_ARITH_ASSIGN_POINT(*)
COMPOUND_ARITH_ASSIGN_POINT(/)


COMPOUND_ARITH_ASSIGN_NUMBER(+)
COMPOUND_ARITH_ASSIGN_NUMBER(-)
COMPOUND_ARITH_ASSIGN_NUMBER(*)
COMPOUND_ARITH_ASSIGN_NUMBER(/)
    

ARITH_POINT_POINT(+)
ARITH_POINT_POINT(-)
ARITH_POINT_POINT(*)
ARITH_POINT_POINT(/)
    
ARITH_NUMBER_POINT(+)
ARITH_NUMBER_POINT(-)
ARITH_NUMBER_POINT(*)
ARITH_NUMBER_POINT(/)
    
ARITH_POINT_NUMBER(+)
ARITH_POINT_NUMBER(-)
ARITH_POINT_NUMBER(*)
ARITH_POINT_NUMBER(/)
    
const POINT_TYPE& POINT_TYPE::operator ++ () {
    if (this->size == 0) {
	ia_throw(IA::POINT_UNINITIALIZED, __FILE__, __LINE__);
	return *this;
    }
    *this += 1;
    return  *this;
}

const POINT_TYPE& POINT_TYPE::operator -- () {
    if (this->size == 0) {
	ia_throw(IA::POINT_UNINITIALIZED, __FILE__, __LINE__);
	return *this;
    }
    *this -= 1;
    return  *this;
}


POINT_TYPE POINT_TYPE::operator - () const
{
    POINT_TYPE result_point;

    if (this->size == 0) {
	ia_throw(IA::POINT_UNINITIALIZED, __FILE__, __LINE__);
	return result_point;
    }

    result_point.coordinates = new TYPE[result_point.size = this->size];

#ifdef NO_LOOP_UNROLLING
    for (unsigned i = 0; i < result_point.size; i++)
	result_point.coordinates[i] =  -this->coordinates[i];
#else
    switch (result_point.size) {
    case 5: result_point.coordinates[4] = -this->coordinates[4];
    case 4: result_point.coordinates[3] = -this->coordinates[3];
    case 3: result_point.coordinates[2] = -this->coordinates[2];
    case 2: result_point.coordinates[1] = -this->coordinates[1];
    case 1: result_point.coordinates[0] = -this->coordinates[0];
    case 0: break;
    default:
    for (unsigned i = 0; i < result_point.size; i++)
	result_point.coordinates[i] =  - this->coordinates[i];
    }
#endif
    return result_point;
}

ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_POINT(%)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_POINT(<<)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_POINT(>>)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_POINT(&)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_POINT(^)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_POINT(|)')

ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_NUMBER(%)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_NUMBER(<<)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_NUMBER(>>)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_NUMBER(&)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_NUMBER(^)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_NUMBER(|)')

ifdef(`INTPOINT', `BITWISE_POINT_POINT(%)')
ifdef(`INTPOINT', `BITWISE_POINT_POINT(<<)')
ifdef(`INTPOINT', `BITWISE_POINT_POINT(>>)')
ifdef(`INTPOINT', `BITWISE_POINT_POINT(&)')
ifdef(`INTPOINT', `BITWISE_POINT_POINT(^)')
ifdef(`INTPOINT', `BITWISE_POINT_POINT(|)')

ifdef(`INTPOINT', `
IntPoint IntPoint::operator ~ () const
{
    IntPoint result_point;
    
    if (this->size == 0) {
	ia_throw(IA::POINT_UNINITIALIZED, __FILE__, __LINE__);
	return *this;
    }

    result_point.coordinates = new int[result_point.size = this->size];

#ifdef NO_LOOP_UNROLLING
    for (unsigned i = 0; i < result_point.size; i++)
	result_point.coordinates[i] =  ~(this->coordinates[i]);
#else
    switch (result_point.size) {
    case 5: result_point.coordinates[4] = ~(this->coordinates[4]);
    case 4: result_point.coordinates[3] = ~(this->coordinates[3]);
    case 3: result_point.coordinates[2] = ~(this->coordinates[2]);
    case 2: result_point.coordinates[1] = ~(this->coordinates[1]);
    case 1: result_point.coordinates[0] = ~(this->coordinates[0]);
    case 0: break;
    default:
    for (unsigned i = 0; i < result_point.size; i++)
	result_point.coordinates[i] =  - this->coordinates[i];
    }
#endif    
    return result_point;
}')


ifdef(`INTPOINT', `BITWISE_NUMBER_POINT(%)')
ifdef(`INTPOINT', `BITWISE_NUMBER_POINT(<<)')
ifdef(`INTPOINT', `BITWISE_NUMBER_POINT(>>)')
ifdef(`INTPOINT', `BITWISE_NUMBER_POINT(&)')
ifdef(`INTPOINT', `BITWISE_NUMBER_POINT(^)')
ifdef(`INTPOINT', `BITWISE_NUMBER_POINT(|)')

ifdef(`INTPOINT', `BITWISE_POINT_NUMBER(%)')
ifdef(`INTPOINT', `BITWISE_POINT_NUMBER(<<)')
ifdef(`INTPOINT', `BITWISE_POINT_NUMBER(>>)')
ifdef(`INTPOINT', `BITWISE_POINT_NUMBER(&)')
ifdef(`INTPOINT', `BITWISE_POINT_NUMBER(^)')
ifdef(`INTPOINT', `BITWISE_POINT_NUMBER(|)')

// Relational operators

// POINT_TYPE < POINT_TYPE    

POINT_POINT_RELATION(<)
POINT_POINT_RELATION(<=)
POINT_POINT_RELATION(>)
POINT_POINT_RELATION(>=)
POINT_POINT_RELATION(==)
POINT_POINT_RELATION(!=)

// POINT_TYPE < int

POINT_INT_RELATION(<)
POINT_INT_RELATION(<=)
POINT_INT_RELATION(>)
POINT_INT_RELATION(>=)
POINT_INT_RELATION(==)
POINT_INT_RELATION(!=)

// int < POINT_TYPE 

INT_POINT_RELATION(<)
INT_POINT_RELATION(<=)
INT_POINT_RELATION(>)
INT_POINT_RELATION(>=)
INT_POINT_RELATION(==)
INT_POINT_RELATION(!=)

// POINT_TYPE < float
    
POINT_FLOAT_RELATION(<)
POINT_FLOAT_RELATION(<=)
POINT_FLOAT_RELATION(>)
POINT_FLOAT_RELATION(>=)
POINT_FLOAT_RELATION(==)
POINT_FLOAT_RELATION(!=)

// float < POINT_TYPE

FLOAT_POINT_RELATION(<)
FLOAT_POINT_RELATION(<=)
FLOAT_POINT_RELATION(>)
FLOAT_POINT_RELATION(>=)
FLOAT_POINT_RELATION(==)
FLOAT_POINT_RELATION(!=)


// Index derangement: "POINT_TYPE (point_index, point_index..)"
//
// Function call overloading on Point gives us a new Point with
// by-point_index selection.  For instance, let  a=Point(10, 20, 30).
// Then b=a(2,0) is equivalent to b=Point(30,10).


POINT_TYPE POINT_TYPE::operator () (unsigned i0) const
{
    POINT_TYPE p(0);
    
    if (i0 >= this->size) {
	ia_throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
	return POINT_TYPE ();
    }
    p.coordinates[0] = this->coordinates[i0];
    return p;
}

POINT_TYPE POINT_TYPE::operator () (unsigned i0, unsigned i1) const
{
    POINT_TYPE p(0,0);

    if (i0 >= this->size || i1 >= this->size) {
	ia_throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
	return POINT_TYPE ();
    }
    p.coordinates[0] = this->coordinates[i0];
    p.coordinates[1] = this->coordinates[i1];
    return p;
}

POINT_TYPE POINT_TYPE::operator () (unsigned i0, unsigned i1, unsigned i2) const
{
    POINT_TYPE p(0,0,0);

    if (i0 >= this->size || i1 >= this->size || i2 >= this->size) {
	ia_throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
	return POINT_TYPE ();
    }
    
    p.coordinates[0] = this->coordinates[i0];
    p.coordinates[1] = this->coordinates[i1];
    p.coordinates[2] = this->coordinates[i2];
    return p;
}

POINT_TYPE POINT_TYPE::operator () (unsigned i0, unsigned i1, unsigned i2, unsigned i3) const
{
    POINT_TYPE p(0,0,0,0);

    if (i0 >= this->size || i1 >= this->size || i2 >= this->size || i3 >= this->size) {
	ia_throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
	return POINT_TYPE ();
    }

    p.coordinates[0] = this->coordinates[i0];
    p.coordinates[1] = this->coordinates[i1];
    p.coordinates[2] = this->coordinates[i2];
    p.coordinates[3] = this->coordinates[i3];
    return p;
}

POINT_TYPE POINT_TYPE::operator () (unsigned i0, unsigned i1, unsigned i2, unsigned i3, unsigned i4) const
{
    POINT_TYPE p(0,0,0,0,0);

    if (i0 >= this->size || i1 >= this->size || i2 >= this->size ||
	i3 >= this->size || i4 >= this->size) {
	ia_throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
	return POINT_TYPE ();
    }

    p.coordinates[0] = this->coordinates[i0];
    p.coordinates[1] = this->coordinates[i1];
    p.coordinates[2] = this->coordinates[i2];
    p.coordinates[3] = this->coordinates[i3];
    p.coordinates[4] = this->coordinates[i4];
    return p;
}
    

// enorm: Euclidean distance from origin.

double POINT_TYPE::enorm () const
{
    double result_number = 0;
    
    for (unsigned i = 0; i < this->size; i++)
	result_number = result_number +
	    (float) (this->coordinates[i] * this->coordinates[i]);

    return sqrt(result_number);
}


// POINT_TYPE = concat (POINT_TYPE, POINT_TYPE)
//
// Given a combination of Points and numbers, create a new Point that is
// the concatenation of the arguments.  Lets the user construct larger
// points than the usual 5 arg constructor.

// TO DO -- These could be modified to not check for zero-length
// points (since we now know that "new foo[0]" returns a deletable
// pointer to one foo that we will never access), and also we could
// do some loop unrolling here as well.

POINT_TYPE concat(const POINT_TYPE& lhs, const POINT_TYPE& rhs)
{
    POINT_TYPE result_point;
    
    if (lhs.size == 0) {
	if (rhs.size == 0)
	    return result_point;
	else 
	    return rhs;
    } else if (rhs.size == 0)
	return lhs;

    unsigned int total_size = lhs.size + rhs.size;

    result_point.coordinates = new TYPE[result_point.size = total_size];
    
    for (unsigned int i = 0; i < lhs.size; i++) 
	result_point.coordinates[i] = lhs.coordinates[i];

    for (unsigned int j = 0; j < rhs.size; j++) 
	result_point.coordinates[i+j] = rhs.coordinates[j];

    return result_point;
}

// POINT_TYPE = concat(POINT_TYPE, TYPE)

POINT_TYPE concat(const POINT_TYPE& lhs, TYPE rhs)
{
    POINT_TYPE result_point;

    if (lhs.size == 0) 
	return POINT_TYPE (rhs);
    
    unsigned int total_size = lhs.size + 1;

    result_point.coordinates = new TYPE[total_size];
    result_point.size = total_size;
    
    for (unsigned int i = 0; i < lhs.size; i++) 
	result_point.coordinates[i] = lhs.coordinates[i];
    
    result_point.coordinates[i] = rhs;
    
    return result_point;
}

// POINT_TYPE = concat(TYPE, POINT_TYPE)

POINT_TYPE concat(TYPE lhs, const POINT_TYPE& rhs)
{
    POINT_TYPE result_point;
    
    if (rhs.size == 0)
	return POINT_TYPE (lhs);

    unsigned int total_size = rhs.size + 1;

    result_point.coordinates = new TYPE[total_size];
    result_point.size = total_size;

    result_point.coordinates[0] = lhs;

    for (unsigned int i = 0; i < rhs.size; i++) 
	result_point.coordinates[i+1] = rhs.coordinates[i];

    return result_point;
}

//  cdr(POINT_TYPE, skip=1):
//
//  Given a point of dimension n, return a point made of the n-skip last
//  coordinates (or if skip is negative, the n+skip first coordinates),
//  where skip defaults to 1.


POINT_TYPE cdr(const POINT_TYPE& pt, int skip = 1) {

    unsigned  abs_skip;

    abs_skip = (skip < 0) ? -skip : skip;
    
    if (pt.size < abs_skip) {
	ia_throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
	return POINT_TYPE ();
    } else if (pt.size == skip)
	return POINT_TYPE ();

    if (skip < 0)
	return POINT_TYPE (pt.coordinates, pt.size+skip);
    else
	return POINT_TYPE (pt.coordinates+skip, pt.size-skip);
}

FRIEND_SELECT_BINARY(min, <)
FRIEND_SELECT_UNARY(min, <)

FRIEND_SELECT_BINARY(max, >)
FRIEND_SELECT_UNARY(max, >)

ifdef(`FLOATPOINT', `
// Math rounding functions as friends.
//  
// All of the following routines perform some rounding function.  Except
// for irint, nint and trunc, the routines always return float points.
// irint, nint, and trunc alway pass back int points.  See rint (3)
// for details.')

ifdef(`FLOATPOINT', `ROUNDING_FLOAT_TO_FLOAT(aint)')
ifdef(`FLOATPOINT', `ROUNDING_FLOAT_TO_FLOAT(anint)')
ifdef(`FLOATPOINT', `ROUNDING_FLOAT_TO_FLOAT(ceil)')
ifdef(`FLOATPOINT', `ROUNDING_FLOAT_TO_FLOAT(floor)')
ifdef(`FLOATPOINT', `ROUNDING_FLOAT_TO_FLOAT(rint)')

ifdef(`FLOATPOINT', `ROUNDING_FLOAT_TO_INT(irint)')
ifdef(`FLOATPOINT', `ROUNDING_FLOAT_TO_INT(nint)')

ifdef(`FLOATPOINT', `
IntPoint trunc(const FloatPoint& p) 
{ 
    int	*iptr;
    iptr = new int[p.size];	    

#ifdef NO_LOOP_UNROLLING
    for (unsigned i = 0; i < p.size; i++) 
	iptr[i] = int(p.coordinates[i]);    
#else
    switch (p.size) {
    case 5: iptr[4] = int(p.coordinates[4]);
    case 4: iptr[3] = int(p.coordinates[3]);
    case 3: iptr[2] = int(p.coordinates[2]);
    case 2: iptr[1] = int(p.coordinates[1]);
    case 1: iptr[0] = int(p.coordinates[0]);
    case 0: break;
    default:
	for (unsigned i = 0; i < p.size; i++) 
	    iptr[i] = int(p.coordinates[i]);
    }
#endif    
    return IntPoint(iptr, p.size, 1);
}')


//  Point comparison: Pointcmp(POINT_TYPE, POINT_TYPE)
//
// A sort of lexicographic comparison of Points, except that
// points are zero extended for comparison, e.g., <1 0> is equal
// to <1>;  <> is equal <0 0 0>, etc. Returns 0 for equality, -1
// if the first is less than the second, 1 if the first is greater
// than the second,

int Pointcmp(const POINT_TYPE &lhs, const POINT_TYPE &rhs)
{
    if (lhs.dimensions() > rhs.dimensions()) {
	for (unsigned i=0; i < rhs.dimensions(); i++) {
	    if (lhs[i] < rhs[i])
		return -1;
	    else if (lhs[i] > rhs[i])
		return 1;
	}
	for ( ; i<lhs.dimensions(); i++) {
	    if (lhs[i] < 0)
		return -1;
	    else if (lhs[i] > 0)
		return 1;
	}
    } else {
	for (unsigned i=0; i < lhs.dimensions(); i++) {
	    if (lhs[i] < rhs[i])
		return -1;
	    else if (lhs[i] > rhs[i])
		return 1;
	}
	for ( ; i < rhs.dimensions(); i++) {
	    if (0 < rhs[i])
		return  -1;
	    else if (0 > rhs[i])
		return  1;
	}
    }
    return 0;

    // If this were to be used for a lexicographic sorter, then we would
    // need the following additional code:
    //
    // At this point the zero-extended Coordinates do not differ in value,
    // so check for number of dimensions; shorter Points are considered
    // less than longer Points.
    // 
    //     if (lhs.dimensions() == rhs.dimensions())
    // 		return 0;
    //     else if (lhs.dimensions() > rhs.dimensions())
    // 		return 1;
    //     else
    // 		return -1;

}
@


2.6
log
@Fixed rscid typo.
@
text
@d3 1
a3 1
static char rcsid[] = "$Id: Point.cc.m4,v 2.5 92/07/29 23:45:24 fischer Exp Locker: fischer $";
d6 3
d220 1
a220 1
	throw(IA::POINT_UNINITIALIZED, __FILE__, __LINE__);
d229 1
a229 1
	throw(IA::POINT_UNINITIALIZED, __FILE__, __LINE__);
d242 1
a242 1
	throw(IA::POINT_UNINITIALIZED, __FILE__, __LINE__);
d294 1
a294 1
	throw(IA::POINT_UNINITIALIZED, __FILE__, __LINE__);
d394 1
a394 1
	throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
d406 1
a406 1
	throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
d419 1
a419 1
	throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
d434 1
a434 1
	throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
d451 1
a451 1
	throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
d572 1
a572 1
	throw(IA::POINT_INDEX_MISMATCH, __FILE__, __LINE__);
@


2.5
log
@Fixed bad rcsid string marker.
@
text
@d3 1
a3 1
static char rscid[] = "$Id$";
d6 3
@


2.4
log
@Changed relational operators to return int, Pointcmp as well.
@
text
@d3 1
a3 1
static char rscid[] = "$Id";
d6 3
@


2.3
log
@Lost pointcmp code between rev 2.0 and 2.1 -- reinserted it.
@
text
@d6 3
d631 1
a631 1
char Pointcmp(const POINT_TYPE &lhs, const POINT_TYPE &rhs)
@


2.2
log
@removed max_dimensions static constant from Point classes.
removed many checks for zero-length points, now that we 
know "new foo[0]" gives us a pointer to one "foo" that can
be safely deleted.  Did some more loop unrolling in functions
like min.  A min-based test program showed 6% speedup 
with g++ -O flag.
@
text
@d6 8
d618 56
@


2.1
log
@fixed problem with nint/rint/trunc pointer.
optimized constructors via loop unrolling.
added min/max as binary (point,point) and
unary (point) functions.
@
text
@d6 6
a41 1
// This doesn't check for zero length sizes:  a question of speed.
a44 1
    if (length == 0) return pt;
d47 1
d58 1
a58 1
	break;
d70 4
a73 2
    this->size = ip.size;
    if (this->size == 0) return;
d75 1
a75 1
    this->coordinates = new TYPE[this->size];
d87 1
a87 1
	break;
d98 1
a98 3
    if (this->size==0) {
	this->coordinates = 0;
    } else if (giveaway) {
d100 5
a104 2
    } else {
	this->coordinates = new TYPE[this->size];
d106 2
a107 2
        for (unsigned length=0; length<this->size; length++)
	    this->coordinates[length] = vec[length];
d109 9
a117 9
        switch (this->size) {
	case 5: this->coordinates[4] = vec[4];
	case 4: this->coordinates[3] = vec[3];
	case 3: this->coordinates[2] = vec[2];
	case 2: this->coordinates[1] = vec[1];
	case 1: this->coordinates[0] = vec[0];
	    break;
	default:
	    for (unsigned length=0; length<this->size; length++)
d119 1
a119 1
	}
a120 1
   }
d123 1
d126 2
a130 7
        if (point.size == 0) {
	delete[] this->coordinates;   // OK even if coordinates already NULL
	this->coordinates = NULL;
	this->size = 0;
	return *this;
    }

d135 1
a135 2
        this->coordinates = new TYPE[point.size];
        this->size = point.size;
d148 1
a148 1
	break;
a175 6
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_POINT(%)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_POINT(<<)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_POINT(>>)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_POINT(&)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_POINT(^)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_POINT(|)')
a181 6
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_NUMBER(%)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_NUMBER(<<)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_NUMBER(>>)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_NUMBER(&)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_NUMBER(^)')
ifdef(`INTPOINT', `COMPOUND_BITWISE_ASSIGN_NUMBER(|)')
d198 63
d268 32
a360 8
const POINT_TYPE& POINT_TYPE::operator ++ () {
    if (this->size == 0) {
	throw(IA::POINT_UNINITIALIZED, __FILE__, __LINE__);
	return *this;
    }
    *this += 1;
    return  *this;
}
a361 49
const POINT_TYPE& POINT_TYPE::operator -- () {
    if (this->size == 0) {
	throw(IA::POINT_UNINITIALIZED, __FILE__, __LINE__);
	return *this;
    }
    *this -= 1;
    return  *this;
}


POINT_TYPE POINT_TYPE::operator - () const
{
    POINT_TYPE result_point;

    if (this->size == 0) {
	throw(IA::POINT_UNINITIALIZED, __FILE__, __LINE__);
	return result_point;
    }

    result_point.size = this->size;
    result_point.coordinates = new TYPE[this->size];

    for (unsigned i = 0; i < result_point.size; i++)
	result_point.coordinates[i] =  - this->coordinates[i];
    return result_point;
}


ifdef(`INTPOINT', `
IntPoint IntPoint::operator ~ () const
{
    IntPoint result_point;
    
    if (this->size == 0) {
	throw(IA::POINT_UNINITIALIZED, __FILE__, __LINE__);
	return *this;
    }

    result_point.size = this->size;
    result_point.coordinates = new int[result_point.size];

    for (unsigned int i=0; i < this->size; i++) {
	result_point.coordinates[i] = ~(this->coordinates[i]);
    }
	    
    return result_point;
}')


d461 2
a462 2
// the concatenation of the arguments.  Throws when the result Point
// would have greater dimension than Point::max_dimensions, currently 5.
d464 4
d483 1
a483 9
    if  (total_size > POINT_TYPE::max_dimensions) {
	throw(IA::POINT_TOO_LARGE, __FILE__, __LINE__);
	return result_point;
    }	    

    if (total_size > 0) {
	result_point.size = total_size;
	result_point.coordinates = new TYPE[total_size];
    }
a504 5
    if  (total_size > POINT_TYPE::max_dimensions) {
	throw(IA::POINT_TOO_LARGE, __FILE__, __LINE__);
	return result_point;
    }

a526 5
    if  (total_size > POINT_TYPE::max_dimensions) {
	throw(IA::POINT_TOO_LARGE, __FILE__, __LINE__);
	return result_point;
    }

d590 14
a603 3
    
    if (p.size != 0) { 
	iptr = new int[p.size];	    
d605 4
a608 4
	    *iptr++ = int(p.coordinates[i]);
	return IntPoint(iptr-p.size, p.size, 1); 	
    } else
	return IntPoint();
@


2.0
log
@Changed from cpp #defines to m4 defines().
@
text
@d5 4
a8 1
// $Log$
d36 2
d40 2
d43 1
d46 13
a60 1
     
d62 1
d66 3
a68 2
    if (this->size == 0)
	return;
d70 1
a70 1
    this->coordinates = new TYPE[this->size];
d73 13
d97 2
a98 1
	for (unsigned length=0; length<this->size; length++)
d100 14
a113 1
    }
a115 1

d135 2
a136 1
    
d138 14
a151 2
        this->coordinates[i] = point.coordinates[i];

a333 14
// enorm: Euclidean distance from origin.

double POINT_TYPE::enorm () const
{
    double result_number = 0;
    
    for (unsigned i = 0; i < this->size; i++)
	result_number = result_number +
	    (float) (this->coordinates[i] * this->coordinates[i]);

    return sqrt(result_number);
}


d416 14
d549 2
a550 7
//  Point comparison: Pointcmp(POINT_TYPE, POINT_TYPE)
//
// A sort of lexicographic comparison of Points, except that
// points are zero extended for comparison, e.g., <1 0> is equal
// to <1>;  <> is equal <0 0 0>, etc. Returns 0 for equality, -1
// if the first is less than the second, 1 if the first is greater
// than the second,
d552 2
a553 30
char Pointcmp(const POINT_TYPE &lhs, const POINT_TYPE &rhs)
{
    if (lhs.dimensions() > rhs.dimensions()) {
	for (unsigned i=0; i < rhs.dimensions(); i++) {
	    if (lhs[i] < rhs[i])
		return -1;
	    else if (lhs[i] > rhs[i])
		return 1;
	}
	for ( ; i<lhs.dimensions(); i++) {
	    if (lhs[i] < 0)
		return -1;
	    else if (lhs[i] > 0)
		return 1;
	}
    } else {
	for (unsigned i=0; i < lhs.dimensions(); i++) {
	    if (lhs[i] < rhs[i])
		return -1;
	    else if (lhs[i] > rhs[i])
		return 1;
	}
	for ( ; i < rhs.dimensions(); i++) {
	    if (0 < rhs[i])
		return  -1;
	    else if (0 > rhs[i])
		return  1;
	}
    }
    return 0;
a554 16
    // If this were to be used for a lexicographic sorter, then we would
    // need the following additional code:
    //
    // At this point the zero-extended Coordinates do not differ in value,
    // so check for number of dimensions; shorter Points are considered
    // less than longer Points.
    // 
    //     if (lhs.dimensions() == rhs.dimensions())
    // 		return 0;
    //     else if (lhs.dimensions() > rhs.dimensions())
    // 		return 1;
    //     else
    // 		return -1;

}

d581 1
a581 1
	return IntPoint(iptr, p.size, 1); 	
@
