mirror of
				https://github.com/RangeNetworks/openbts.git
				synced 2025-11-04 05:43:14 +00:00 
			
		
		
		
	git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@2307 19bc5d8c-e614-43d4-8b26-e1612bc8e597
		
			
				
	
	
		
			268 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			268 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/**@file templates for Complex classes
 | 
						|
unlike the built-in complex<> templates, these inline most operations for speed
 | 
						|
*/
 | 
						|
 | 
						|
/*
 | 
						|
* Copyright 2008 Free Software Foundation, Inc.
 | 
						|
*
 | 
						|
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
 | 
						|
*
 | 
						|
* This use of this software may be subject to additional restrictions.
 | 
						|
* See the LEGAL file in the main directory for details.
 | 
						|
 | 
						|
    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.
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#ifndef COMPLEXCPP_H
 | 
						|
#define COMPLEXCPP_H
 | 
						|
 | 
						|
#include <math.h>
 | 
						|
#include <ostream>
 | 
						|
 | 
						|
 | 
						|
template<class Real> class Complex {
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
  Real r, i;
 | 
						|
 | 
						|
  /**@name constructors */
 | 
						|
  //@{
 | 
						|
  /**@name from real */
 | 
						|
  //@{
 | 
						|
  Complex(Real real, Real imag) {r=real; i=imag;}	// x=complex(a,b)
 | 
						|
  Complex(Real real) {r=real; i=0;}			// x=complex(a)
 | 
						|
  //@}
 | 
						|
  /**@name from nothing */
 | 
						|
  //@{
 | 
						|
  Complex() {r=(Real)0; i=(Real)0;}			// x=complex()
 | 
						|
  //@}
 | 
						|
  /**@name from other complex */
 | 
						|
  //@{
 | 
						|
  Complex(const Complex<float>& z) {r=z.r; i=z.i;}	// x=complex(z)
 | 
						|
  Complex(const Complex<double>& z) {r=z.r; i=z.i;}	// x=complex(z)
 | 
						|
  Complex(const Complex<long double>& z) {r=z.r; i=z.i;}	// x=complex(z)
 | 
						|
  //@}
 | 
						|
  //@}
 | 
						|
 | 
						|
  /**@name casting up from basic numeric types */
 | 
						|
  //@{
 | 
						|
  Complex& operator=(char a) { r=(Real)a; i=(Real)0; return *this; }
 | 
						|
  Complex& operator=(int a) { r=(Real)a; i=(Real)0; return *this; }
 | 
						|
  Complex& operator=(long int a) { r=(Real)a; i=(Real)0; return *this; }
 | 
						|
  Complex& operator=(short a) { r=(Real)a; i=(Real)0; return *this; }
 | 
						|
  Complex& operator=(float a) { r=(Real)a; i=(Real)0; return *this; }
 | 
						|
  Complex& operator=(double a) { r=(Real)a; i=(Real)0; return *this; }
 | 
						|
  Complex& operator=(long double a) { r=(Real)a; i=(Real)0; return *this; }
 | 
						|
  //@}
 | 
						|
 | 
						|
  /**@name arithmetic */
 | 
						|
  //@{
 | 
						|
  /**@ binary operators */
 | 
						|
  //@{
 | 
						|
  Complex operator+(const Complex<Real>& a) const { return Complex<Real>(r+a.r, i+a.i); }
 | 
						|
  Complex operator+(Real a) const { return Complex<Real>(r+a,i); }
 | 
						|
  Complex operator-(const Complex<Real>& a) const { return Complex<Real>(r-a.r, i-a.i); }
 | 
						|
  Complex operator-(Real a) const { return Complex<Real>(r-a,i); }
 | 
						|
  Complex operator*(const Complex<Real>& a) const { return Complex<Real>(r*a.r-i*a.i, r*a.i+i*a.r); }
 | 
						|
  Complex operator*(Real a) const { return Complex<Real>(r*a, i*a); }
 | 
						|
  Complex operator/(const Complex<Real>& a) const { return operator*(a.inv()); }
 | 
						|
  Complex operator/(Real a) const { return Complex<Real>(r/a, i/a); }
 | 
						|
  //@}
 | 
						|
  /*@name component-wise product */
 | 
						|
  //@{
 | 
						|
  Complex operator&(const Complex<Real>& a) const { return Complex<Real>(r*a.r, i*a.i); }
 | 
						|
  //@}
 | 
						|
  /*@name inplace operations */
 | 
						|
  //@{
 | 
						|
  Complex& operator+=(const Complex<Real>&);
 | 
						|
  Complex& operator-=(const Complex<Real>&);
 | 
						|
  Complex& operator*=(const Complex<Real>&);
 | 
						|
  Complex& operator/=(const Complex<Real>&);
 | 
						|
  Complex& operator+=(Real);
 | 
						|
  Complex& operator-=(Real);
 | 
						|
  Complex& operator*=(Real);
 | 
						|
  Complex& operator/=(Real);
 | 
						|
  //@}
 | 
						|
  //@}
 | 
						|
 | 
						|
  /**@name comparisons */
 | 
						|
  //@{
 | 
						|
  bool operator==(const Complex<Real>& a) const { return ((i==a.i)&&(r==a.r)); }
 | 
						|
  bool operator!=(const Complex<Real>& a) const { return ((i!=a.i)||(r!=a.r)); }
 | 
						|
  bool operator<(const Complex<Real>& a) const { return norm2()<a.norm2(); }
 | 
						|
  bool operator>(const Complex<Real>& a) const { return norm2()>a.norm2(); }
 | 
						|
  //@}
 | 
						|
 | 
						|
  /// reciprocation
 | 
						|
  Complex inv() const;	
 | 
						|
 | 
						|
  // unary functions -- inlined
 | 
						|
  /**@name unary functions */
 | 
						|
  //@{
 | 
						|
  /**@name inlined */
 | 
						|
  //@{
 | 
						|
  Complex conj() const { return Complex<Real>(r,-i); }
 | 
						|
  Real norm2() const { return i*i+r*r; }
 | 
						|
  Complex flip() const { return Complex<Real>(i,r); }
 | 
						|
  Real real() const { return r;}
 | 
						|
  Real imag() const { return i;}
 | 
						|
  Complex neg() const { return Complex<Real>(-r, -i); }
 | 
						|
  bool isZero() const { return ((r==(Real)0) && (i==(Real)0)); }
 | 
						|
  //@}
 | 
						|
  /**@name not inlined due to outside calls */
 | 
						|
  //@{
 | 
						|
  Real abs() const { return ::sqrt(norm2()); }
 | 
						|
  Real arg() const { return ::atan2(i,r); }
 | 
						|
  float dB() const { return 10.0*log10(norm2()); }
 | 
						|
  Complex exp() const { return expj(i)*(::exp(r)); }
 | 
						|
  Complex unit() const; 			///< unit phasor with same angle
 | 
						|
  Complex log() const { return Complex(::log(abs()),arg()); }
 | 
						|
  Complex pow(double n) const { return expj(arg()*n)*(::pow(abs(),n)); }
 | 
						|
  Complex sqrt() const { return pow(0.5); }
 | 
						|
  //@}
 | 
						|
  //@}
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**@name standard Complex manifestations */
 | 
						|
//@{
 | 
						|
typedef Complex<float> complex;
 | 
						|
typedef Complex<double> dcomplex;
 | 
						|
typedef Complex<short> complex16;
 | 
						|
typedef Complex<long> complex32;
 | 
						|
//@}
 | 
						|
 | 
						|
 | 
						|
template<class Real> inline Complex<Real> Complex<Real>::inv() const
 | 
						|
{
 | 
						|
  Real nVal;
 | 
						|
 | 
						|
  nVal = norm2();
 | 
						|
  return Complex<Real>(r/nVal, -i/nVal);
 | 
						|
}
 | 
						|
 | 
						|
template<class Real> Complex<Real>& Complex<Real>::operator+=(const Complex<Real>& a)
 | 
						|
{
 | 
						|
  r += a.r;
 | 
						|
  i += a.i;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
template<class Real> Complex<Real>& Complex<Real>::operator*=(const Complex<Real>& a)
 | 
						|
{
 | 
						|
  operator*(a);
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
template<class Real> Complex<Real>& Complex<Real>::operator-=(const Complex<Real>& a)
 | 
						|
{
 | 
						|
  r -= a.r;
 | 
						|
  i -= a.i;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
template<class Real> Complex<Real>& Complex<Real>::operator/=(const Complex<Real>& a)
 | 
						|
{
 | 
						|
  operator/(a);
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* op= style operations with reals */
 | 
						|
 | 
						|
template<class Real> Complex<Real>& Complex<Real>::operator+=(Real a)
 | 
						|
{
 | 
						|
  r += a;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
template<class Real> Complex<Real>& Complex<Real>::operator*=(Real a)
 | 
						|
{
 | 
						|
  r *=a;
 | 
						|
  i *=a;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
template<class Real> Complex<Real>& Complex<Real>::operator-=(Real a)
 | 
						|
{
 | 
						|
  r -= a;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
template<class Real> Complex<Real>& Complex<Real>::operator/=(Real a)
 | 
						|
{
 | 
						|
  r /= a;
 | 
						|
  i /= a;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
template<class Real> Complex<Real> Complex<Real>::unit() const
 | 
						|
{
 | 
						|
  Real absVal = abs();
 | 
						|
  return (Complex<Real>(r/absVal, i/absVal));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**@name complex functions outside of the Complex<> class. */
 | 
						|
//@{
 | 
						|
 | 
						|
/** this allows type-commutative multiplication */
 | 
						|
template<class Real> Complex<Real> operator*(Real a, const Complex<Real>& z)
 | 
						|
{
 | 
						|
  return Complex<Real>(z.r*a, z.i*a);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/** this allows type-commutative addition */
 | 
						|
template<class Real> Complex<Real> operator+(Real a, const Complex<Real>& z)
 | 
						|
{
 | 
						|
  return Complex<Real>(z.r+a, z.i);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/** this allows type-commutative subtraction */
 | 
						|
template<class Real> Complex<Real> operator-(Real a, const Complex<Real>& z)
 | 
						|
{
 | 
						|
  return Complex<Real>(z.r-a, z.i);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/// e^jphi
 | 
						|
template<class Real> Complex<Real> expj(Real phi)
 | 
						|
{
 | 
						|
  return Complex<Real>(cos(phi),sin(phi));
 | 
						|
}
 | 
						|
 | 
						|
/// phasor expression of a complex number
 | 
						|
template<class Real> Complex<Real> phasor(Real C, Real phi)
 | 
						|
{
 | 
						|
  return (expj(phi)*C);
 | 
						|
}
 | 
						|
 | 
						|
/// formatted stream output
 | 
						|
template<class Real> std::ostream& operator<<(std::ostream& os, const Complex<Real>& z)
 | 
						|
{
 | 
						|
  os << z.r << ' ';
 | 
						|
  //os << z.r << ", ";
 | 
						|
  //if (z.i>=0) { os << "+"; }
 | 
						|
  os << z.i << "j";
 | 
						|
  os << "\n";
 | 
						|
  return os;
 | 
						|
}
 | 
						|
 | 
						|
//@}
 | 
						|
 | 
						|
 | 
						|
#endif
 |