// -*- Mode: c++ -*-
// $Id: utils.H,v 1.1 1998/02/10 17:45:07 neel Exp $
// $Source: /u2/graphics/projects/6.838/gvis/gprims/utils.H,v $

#ifndef	__UTILS_H__
#define	__UTILS_H__

static char
__rcs_ref_util_h( void )
{
  static char rcs_id_h[] = "$Header: /u2/graphics/projects/6.838/gvis/gprims/utils.H,v 1.1 1998/02/10 17:45:07 neel Exp $";
  return rcs_id_h[0];
}
// Do not change anything above this line
static char avoid_stupid_compiler_warnings2 = __rcs_ref_util_h();

#include <iostream.h>
#include <assert.h>
#include "constants.H"


// used by float3, float4
enum INDEXES  {
  X = 0,
  Y = 1,
  Z = 2,
  W = 2
};

//#if _NO_ANSIMODE
//#else

#ifdef __ANSI_CPP__
// for ANSI C, MAX_FLOAT, FLT_MAX, or HUGE are not defined
#define	FLT_MAX		3.40282347E+38F /* max decimal value of a "float" */
// #define rand()          random()
#endif




// Inline function definitions go here
inline float
minf(float a,float b)
{
  return a <= b ? a : b; // use <= to maintain order
}

template <class _type>
inline _type
max( _type a, _type b )
{
  return a >= b ? a : b; // use >= to maintain order
}

template <class _type>
inline _type
min( _type a, _type b )
{
  return a <= b ? a : b; // use <= to maintain order
}

template <class _type>
inline _type
min( _type a, _type b, _type c )
{
  _type m = min( a, b );
  return min( m, c );
}

template <class _type>
inline _type
max( _type a, _type b, _type c )
{
  _type m = max( a, b );
  return max( m, c );
}

template <class _type>
inline _type
min( _type a, _type b, _type c, _type d )
{
  _type m = min( a, b );
  m = min( m, c );
  return min( m, d );
}

template <class _type>
inline _type
max( _type a, _type b, _type c, _type d )
{
  _type m = max( a, b );
  m = max( m, c );
  return max( m, d );
}

template <class _type>
inline int
sign( const _type f )
{
  return f < 0 ? -1 : ( f > 0 ? 1 : 0 );
}

template <class _type>
inline _type
abs( const _type f )
{
  return f < 0 ? -f : f;
}

template <class _type>
inline _type
sqr( const _type s )
{
  return s * s;
}

template <class _type>
inline _type
cube( const _type s )
{
  return s * s * s;
}

inline int
even( int i )
{
  return !( i % 2 );
}

inline int
odd( int i )
{
  return i % 2;
}

inline int
zero( const float x, const float eps )
{
  return ( -eps < x ) && ( x < eps );
}

extern float __negeps_f;
extern float __poseps_f;

inline int
zero( const float x )
{
  return ( __negeps_f < x ) && ( x < __poseps_f );
}

// the SGI compiler made me do it.... #$%&*#^!
#define	ZERO(x)	(( __negeps_f<(x))&&((x)<__poseps_f))

// Strictly positive.
inline int
positive(const float x)
{
  return x >= __poseps_f;
}

// Strictly negative.
inline int
negative(const float x)
{
  return x <= __negeps_f;
}

inline int
less_equals(const float a, const float b)
{
  return a <= b + __poseps_f;
}

inline int
greater_equals(const float a, const float b)
{
  return a >= b - __poseps_f;
}

// extern defs for non-member outline functions go here
// externally visible constant defs go here

extern int nan( const float &x, const int verbose = 0 );

// should be called only for positive powers of two
extern int logbasetwo( int x );
// called for nonnegative integers
extern int ispoweroftwo( int x );
// returns next n >= x such that n = 2^integer
extern int nextpoweroftwo( int x );

extern float det22 (
       float a, float b,
       float c, float d);

extern float det33 (
       float a, float b, float c, 
       float d, float e, float f, 
       float g, float h, float i);

extern float det44 (
       float a, float b, float c, float d,
       float e, float f, float g, float h,
       float i, float j, float k, float l,
       float m, float n, float o, float p);

// align to given block size
extern int align( const int nbytes, const int wordsize );

const float one = 1.f;
const float one_half = 1.f / 2;
const float one_third = 1.f / 3;
const float two_thirds = 2.f / 3;

// utils.H
void  randomColor ( float *rgbcol );


#endif	/* __UTIL_H__ */




