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

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

#ifndef IA_NO_RCS_STATIC_DATA
static char copyright[] = "Copyright 1993, Center for Computer Vision and Visualization,\nUniversity of Florida.  All rights reserved.\n";

static char rcsid[] = "$Id: ia.c,v 1.14.1.1 1995/01/08 17:24:51 thoth Exp thoth $";
#endif

//
// $Log: ia.c,v $
//Revision 1.14.1.1  1995/01/08  17:24:51  thoth
//Special rand_mod function for use by IA module so we can
//easily modify it in one place and affect the entire IAC++
//(for porting).
//
//Revision 1.14  1994/11/10  18:39:06  ljr
//Added IA_NO_RCS_STATIC_DATA guard.
//
//Revision 1.13  1994/11/10  18:33:45  thoth
//g++ pragmas
//
//Revision 1.12  1994/08/22  15:07:02  thoth
//stream.h should always be replaced by iostream.h
//cast to int is fine for all compilers.
//
//Revision 1.11  1994/08/17  02:07:58  gmt
//Changed to not include stream.h or iostream.h since ia.h includes
//iostream.h.
//Also, had to do an explicit cast to int when printint an exception
//number.
//(Note: all these changes are for the Mac version.)
//
//Revision 1.10  1994/08/04  08:38:13  ljr
//Changed to #include <iostream.h> instead of <stream.h> with BC++.
//
//Revision 1.9  1994/01/31  16:29:52  thoth
//renaming exit_on_throw.
//adding some convenience functions that make it easy to
//document an internal error or NYI.
//new exceptions for ia_throw.
//new version of ia_throw that takes an object.
//
//Revision 1.8  1993/11/16  13:25:01  thoth
//Add PNM IO error.
//
//Revision 1.7  1993/09/24  14:22:40  jnw
//Added initialization for IA:: class version data members
//
//Revision 1.6  93/09/15  12:23:13  thoth
//Some pointset behavior controls.
//
//Revision 1.5  93/05/26  16:28:11  thoth
//Copyright Notices.
//
//Revision 1.4  93/05/26  16:04:10  thoth
//New Error type for IAAIO
//
//Revision 1.3  92/10/05  16:55:44  jnw
//Added error names
//
//Revision 1.2  92/08/27  15:29:52  jnw
//changed to use <stream.h> rather than <iostream.h>
//Modified another bad comment (gcc-cpp sux)
//
//Revision 1.1  92/08/25  11:30:47  jnw
//Initial revision
//
//

#include <iostream.h>
#include <stdlib.h>
#include <rand48.h>

#include "compat.h"
#ifdef IA_PRII
#pragma implementation "ia.h"
#endif
#include "ia.h"

#if 0
/*
// The following array relies on the fact that the enum NONE for the
// enumerated type NumericType in file ``ia.h'',  will be the last of
// the enumerated types, and that the enumerated types  are indexed
// from zero: let (int)NONE == N. Then ContagionTable below is indexed
// over [0..N-1][0..N-1], just what we  want.
//
// Also note that the ContagionTable currently doesn't have any
// entries NONE,  though  this is certainly possible if we get two
// numeric types that are not coercible to a common type, for instance
// RGB colorspace and REAL.
*/
const NumericType IA::ContagionTable[(int)NONE][(int)NONE] = {
    {INTEGER,  RATIONAL,  REAL,    COMPLEX},
    {RATIONAL, RATIONAL,  REAL,    COMPLEX},
    {REAL,     REAL,      REAL,    COMPLEX},
    {COMPLEX,  COMPLEX,   COMPLEX, COMPLEX}
};
#endif

int IA::abort_on_throw = 1;
char IA::throw_on_index_uncontained =1;
const unsigned IA::index_of_uncontained = ~0;
const int IA::major_version_number = IA_MAJOR_VERSION_NUMBER;
const int IA::minor_version_number = IA_MINOR_VERSION_NUMBER;

#if 0
NumericType IA::lowest_type()
{
    return (NumericType) 0;
}

// If result_type is modified to return NONE as a possibility, nearly
// all operators  in Coord.cc (at least) will have to be rewritten.

NumericType IA::result_type (NumericType first, NumericType second)
{
    NumericType   result_type;

    if (first==NONE || second==NONE)
        ia_throw(TYPE_UNSPECIFIED, __FILE__, __LINE__);

    result_type = ContagionTable[first][second];

/*    // Can't happen (yet).
*/

    if (result_type==NONE)
        ia_throw(TYPE_MISMATCH, __FILE__, __LINE__);

    return result_type; // too pascalish :)
}

ostream &operator<<(ostream &stream, NumericType type)
{
    switch (type) {
    case INTEGER:
	stream << "INTEGER";
	break;
    case REAL:
	stream << "REAL";
	break;
    case RATIONAL:
	stream << "RATIONAL";
	break;
    case COMPLEX:
	stream << "COMPLEX";
	break;
    case NONE:
	stream << "NONE";
	break;
    default:
	stream << "Unknown?!";
	break;
    }
    return stream;
}
#endif


VOL_F void IA::internal_error(char *file, int line)
{
    cerr << "IAC++ internal error @ "
	<< file << ":" << line << ".  Aborting.\n" << flush;
    abort();
}

VOL_F void IA::not_yet_implemented(char *file, int line)
{
    cerr << "IAC++ Error: Feature not yet implemented @ "
	<< file << ":" << line << ".  Aborting.\n" << flush;
    abort();
}

#if 0
VOL_F void ia_throw(IA::Error e, char *file, int line)
{
    cerr << "throw: fatal ";
    switch (e) {
	// IA:: is necessary here
    case IA::TYPE_MISMATCH:
	cerr << "Type Mismatch";
	break;
    case IA::TYPE_UNSPECIFIED:
	cerr << "Type Unspecified";
	break;
    case IA::POINT_INDEX_MISMATCH:
	cerr << "Point Index Mismatch";
	break;
    case IA::POINT_UNINITIALIZED:
	cerr << "Point Uninitialized";
	break;
    case IA::POINT_TOO_LARGE:
        cerr << "Result Point has too many dimensions";
        break;
    case IA::INVALID_OPERATION:
	cerr << "Invalid Operation";
	break;
    case IA::PSET_REQUIRE_EXTENSIVE:
	cerr << "Operation requires an extensive PointSet";
	break;
    case IA::PSET_DIMENSION_MISMATCH:
	cerr << "Dimensions of argument PointSets don't match";
	break;
    case IA::PSET_INDEX_UNCONTAINED:
	cerr << "Operation tried to index point not contained in a PointSet";
	break;
    case IA::PSET_SIZE_MISMATCH:
	cerr << "Cardinality of argument PointSet is not correct";
	break;
    case IA::IMAGE_REQUIRE_VALUE:
	cerr << "Operation requires image arguments to have values";
	break;
    case IA::IMAGE_REQUIRE_EXTENSIVE:
	cerr << "Operation requires extensive image arguments";
	break;
    case IA::IMAGE_STRUCTURE_NOT_SUPPORTED:
	cerr << "Operation is undefined on images with the specified structure";
	break;
    case IA::PSET_MISMATCH:
	cerr << "Operation is defined only with exactly matching PointSets";
	break;
    case IA::IMAGE_DOMAIN_ERROR:
	cerr << "Operation attempted to find a point not in an image's domain";
	break;
    case IA::IMAGE_REQUIRE_VALUE_ITER:
	cerr << "Operation requires an image value iterator";
	break;
    case IA::IMAGE_REQUIRE_PIXEL_ITER:
	cerr << "Operation requires an image pixel iterator";
	break;
    case IA::IMAGE_VECTOR_CNSTR_SZMISMATCH:
	cerr << "Vector size mismatch in vector image constructor";
	break;
    case IA::IMAGE_POINT_OUTSIDE_DOMAIN:
	cerr << "Attempt to reference image value outside image domain";
	break;
    case IA::IAAIO_FORMAT_ERROR:
	cerr << "Format error during IAA file I/O";
	break;
    case IA::PNM_IO_ERROR:
	cerr << "Error during PNM file I/O";
	break;
    default:
	cerr << "unnamed exception (" << ( int )e << ")";
	break;
    }
    cerr << " at " << file << ':' << line << ".\n";

    if (IA::abort_on_throw)
	abort();
}
#endif

VOL_F void ia_throw(const IA::Exception &e)
{
    e.diagnose(cerr);

    if (IA::abort_on_throw)
	abort();
}

//

ostream &GenericException::diagnose(ostream &o) const
{
    return o << "throw: fatal " << explanation
	<< " at " << filename << ":" << line << ".\n";

}

//

int IA::rand_mod(int modulus)
{
    return lrand48()%modulus;
}
