/*
 *  hrdarth.h from ObjectProDSP 0.2
 *  Copyright (C) 1994 1995, Mountain Math Software. All rights reserved.
 *  
 *  This file is part of ObjectProDSP, a tool for Digital Signal
 *  Processing design, development and implementation. It is free
 *  software provided you use and distribute it under the terms of
 *  version 2 of the GNU General Public License as published
 *  by the Free Software Foundation. You may NOT distribute it or
 *  works derived from it or code that it generates under ANY
 *  OTHER terms.  In particular NONE of the ObjectProDSP system is
 *  licensed for use under the GNU General Public LIBRARY License.
 *  Mountain Math Software plans to offer a commercial version of
 *  ObjectProDSP for a fee. That version will allow redistribution
 *  of generated code under standard commercial terms.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of version 2 of the GNU General
 *  Public License along with this program. See file COPYING. If not
 *  or if you wish information on commercial versions and licensing
 *  write Mountain Math Software, P. O. Box 2124, Saratoga, CA 95070,
 *  USA, or send us e-mail at: support@mtnmath.com.
 *  
 *  You may also obtain the GNU General Public License by writing the
 *  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 *  USA.  However if you received a copy of this program without the
 *  file COPYING or without a copyright notice attached to all text
 *  files, libraries and executables please inform Mountain Math Software.
 *  
 *  ObjectProDSP is a trademark of Mountain Math Software.
 */
/*  hrdarth.h   */
/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */

// Class definitions for hardware arithmentic.
// The actual arithmetic functions are in "hrdcmp.h"
// so they do not to be included whenver size only information is needed.

#ifndef HRDARTH_DOT_H
#define HRDARTH_DOT_H

#ifndef OVERFLOW
#include <complex.h>
#endif 

#include "ObjProDSP/portable.h"
#include "ObjProDSP/arthtyp.h"

#define TheArithType ArithType::ArithInt16

class CxAccMachWord ;
class AccMachWord ;
class CxMachWord ;

typedef uint16 BinMachWord ;
typedef uint16 UnsignedIntegerMachWord ; // Use this, BinMachWord is obsolete

typedef int16 SignedBinMachWord ;
typedef int16 IntegerMachWord ; // use this SignedBinMachWord is obsolete

typedef int16 MachWordCast ;
typedef int32 AccMachWordCast ;

class MachWord{
friend AccMachWord;
friend inline double GetDoubleFromPtr(MachWord *);
friend complex GetComplexFromPtr(CxMachWord * v) ;
	int16 value;
public:
	operator int16() const {return value;}
	operator double() const {return value;}
	MachWord(const MachWord& x) {value = x.value;}
	MachWord() {value = 0;}
	MachWord(uint16 v) {value = v;}
	MachWord(int16 v) {value = v;}
	MachWord(unsigned int v);
	MachWord(int v) ;
	MachWord(double v) ;
	int16 val() const {return value;}
	MachWord operator-() const {return MachWord(-value);}
	inline void operator+=(MachWord) ;
	inline void operator-=(MachWord) ;
	inline void operator*=(MachWord) ;
	inline void operator/=(MachWord) ;
	inline void operator|=(MachWord) ;
	inline void operator&=(MachWord) ;
	inline void operator^=(MachWord) ;
	inline void operator%=(MachWord) ;
	inline int operator<(MachWord) const ;
	inline int operator>(MachWord) const ;
	inline int operator<=(MachWord) const ;
	inline int operator>=(MachWord) const ;
	inline int operator==(MachWord) const ;
	inline int operator!=(MachWord) const ;
	inline void operator<<=(int) ;
	inline void operator>>=(int) ;
	static const int16 max_positive ;
    static const int16 min_negative ;
    static const int16 max_int_positive ;
    static const int16 min_int_negative ;
    static const uint16 max_unsigned_int ;
	static MachWordCast convert_MachWord_check(IntegerMachWord);
	static int32 convert_int32_check(MachWord v);
	static IntegerMachWord convert_check(MachWord v);
    static IntegerMachWord convert_int_check(int32);
    static UnsignedIntegerMachWord convert_unsigned_int_check(int32);
    static IntegerMachWord convert_int_check(double);
    static UnsignedIntegerMachWord convert_unsigned_int_check(double);
    static void hard_limit_warn(const char * type = "MachWord");
};

inline double GetDoubleFromPtr(MachWord *Ptr) { return (double) Ptr->value;}

class AccMachWord {
friend inline double GetDoubleFromPtr(AccMachWord *);
friend complex GetComplexFromPtr(CxAccMachWord * v) ;
	int32 value;
public:
	operator int32() const { return value;}
	AccMachWord(MachWord v)  {value = v.value;}
	AccMachWord(int32 v=0) {value=v;}
	AccMachWord(uint32 v) ;
	AccMachWord(double v) ;
	AccMachWord operator-() const {return AccMachWord(-value);}
	double val() const {return value;}
	// void operator=(AccMachWord val) {value = val;}
	inline void operator+=(AccMachWord);
	inline void operator-=(AccMachWord);
	inline void operator*=(AccMachWord);
	inline void operator/=(AccMachWord);
	inline void operator|=(AccMachWord);
	inline void operator&=(AccMachWord);
	inline void operator^=(AccMachWord);
	inline void operator%=(AccMachWord);
	inline int operator<(AccMachWord) const ;
	inline int operator>(AccMachWord) const ;
	inline int operator<=(AccMachWord) const ;
	inline int operator>=(AccMachWord) const ;
	inline int operator==(AccMachWord) const ;
	inline int operator!=(AccMachWord) const ;
	inline void operator<<=(int) ;
	inline void operator>>=(int) ;
	static const int32 max_positive ;
    static const int32 min_negative ;
};

inline double GetDoubleFromPtr(AccMachWord *Ptr) { return (double) Ptr->value;}

inline MachWord MachReal(const CxMachWord& a);
inline MachWord MachImag(const CxMachWord& a);

class CxMachWord{
friend complex GetComplexFromPtr(CxMachWord * v) ;
	MachWord rl;
	MachWord ig;
public:
	CxMachWord(int16 r=0,int16 i=0) {rl=MachWord(r);ig=MachWord(i);}
	CxMachWord(MachWord r)		{ rl = r; ig = (int16) 0;}
	CxMachWord(MachWord r, MachWord i) { rl =r ; ig = i;}
	CxMachWord(const CxMachWord& x)	{rl = MachReal(x), ig = MachImag(x);}
	CxMachWord(const complex& x) {rl = real(x), ig = imag(x);}
	CxMachWord operator-() const {return CxMachWord(-rl,-ig);}
	// void operator=(CxMachWord v) {rl =MachReal(v); ig = MachImag(v);}
	void operator+=(const CxMachWord&);
	void operator-=(const CxMachWord&);
	void operator*=(const CxMachWord&);
	void operator*=(MachWord);
	void operator/=(const CxMachWord&);
	void operator/=(MachWord);
	void operator|=(const CxMachWord&);
	void operator&=(const CxMachWord&);
	void operator^=(const CxMachWord&);
	void operator%=(const CxMachWord&);
	void operator<<=(int) ;
	void operator>>=(int) ;
	operator complex() const ;
	inline friend MachWord MachReal(const CxMachWord&);
	inline friend MachWord MachImag(const CxMachWord&);
	inline friend CxMachWord conj (const CxMachWord&);
};

inline CxMachWord conj(const CxMachWord& arg)
{
	return CxMachWord(arg.rl, -arg.ig);
}


inline MachWord MachReal(const CxMachWord& a)
{
	return a.rl;
}

inline MachWord MachImag(const CxMachWord& a)
{
	return a.ig;
}

class CxAccMachWord ;
inline AccMachWord MachReal(const CxAccMachWord& );
inline AccMachWord MachImag(const CxAccMachWord& );

class CxAccMachWord {
friend complex GetComplexFromPtr(CxAccMachWord * v) ;
	AccMachWord Real;
	AccMachWord Imag;
public:
	CxAccMachWord(int32 r=0,int32 i=0) {Real=r;Imag=i;}
	CxAccMachWord(const CxMachWord& W)
			{Real = MachReal(W) ; Imag = MachImag(W); }
	CxAccMachWord(const CxAccMachWord& W)
			{Real = MachReal(W) ; Imag = MachImag(W); }
	CxAccMachWord(AccMachWord R, AccMachWord I) {Real = R ; Imag = I ; }
	CxAccMachWord(MachWord R,MachWord I)
		{Real = R ; Imag = I ; }
	CxAccMachWord(const complex& x) {Real = real(x), Imag = imag(x);}
	CxAccMachWord operator-() const
		{return CxAccMachWord(-Real, -Imag);}
	// void operator=(CxAccMachWord v)
	//	{Real = MachReal(v) ; Imag = MachImag(v);}
	void operator+=(const CxAccMachWord&);
	void operator-=(const CxAccMachWord&);
	void operator*=(const CxAccMachWord&);
	void operator*=(AccMachWord);
	void operator/=(const CxAccMachWord&);
	void operator/=(AccMachWord);
	void operator|=(const CxAccMachWord&);
	void operator&=(const CxAccMachWord&);
	void operator^=(const CxAccMachWord&);
	void operator%=(const CxAccMachWord&);
	operator complex() const {return complex(Real,Imag);}
	friend AccMachWord MachReal(const CxAccMachWord& );
	inline friend AccMachWord MachImag(const CxAccMachWord& );
	inline friend CxAccMachWord conj (const CxAccMachWord& );
};

inline CxAccMachWord conj(const CxAccMachWord& arg)
{
	return CxAccMachWord(arg.Real, -arg.Imag);
}

inline AccMachWord MachReal(const CxAccMachWord& a)
{
	return a.Real ;
}

inline AccMachWord MachImag(const CxAccMachWord& a)
{
	return a.Imag ;
}

struct CxAccMachWordType {
	int32 r;
	int32 i;
} ; 			// Used to initalize arrays of 'CxAccMachWords'

struct CxMachWordType {
	int16 r;
	int16 i;
} ; 			// Used to initalize arrays of 'CxMachWords'

struct AccMachWordType {
	int32 v;
} ; 			// Used to initalize arrays of 'AccMachWords'

struct MachWordType {
	int16 v;
} ; 			// Used to initalize arrays of 'MachWords'

CxMachWord MakeCxMachWord(const complex&);
CxAccMachWord MakeCxAccMachWord(const complex&);

complex GetComplexFromPtr(MachWord * v) ;
complex GetComplexFromPtr(AccMachWord * v);


#define DEF_MACH_WORD_MAX  0x7fff
#define DEF_MACH_WORD_MIN -DEF_MACH_WORD_MAX
#define DEF_ACC_MACH_WORD_MAX  0x7fffffff
#define DEF_ACC_MACH_WORD_MIN -DEF_ACC_MACH_WORD_MAX
#define INTEGER_MACH_WORD_TYPE

#define NormToOneMachWord ((int32) 0x8000) 

typedef int32 OverflowCheck ;
#define OverflowCheckMax MaxAccPositiveVal
extern MachWord check_overflow(double test_val,int32& number_overflows);
extern AccMachWord check_overflow_acc(double test_val,int32& number_overflows);

extern MachWord NormToMachWord(double v);
extern AccMachWord NormToAccMachWord(double v);
// these routines give warnings the following two do not and are
// usable in static initializers
extern MachWord NormToHardLimitMachWord(double v);
extern AccMachWord NormToHardLimitAccMachWord(double v);


extern double NormFromMachWord(double val) ;
extern double NormFromAccMachWord(double val) ;



#define MachWordZero ((MachWord) (int16) 0)

#endif /* #ifdef HRDARTH_DOT_H */

