mirror of
				https://github.com/RangeNetworks/openbts.git
				synced 2025-10-30 19:33:33 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			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.
 | |
| * Copyright 2014 Range Networks, Inc.
 | |
| *
 | |
| * This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribution.
 | |
| *
 | |
| * 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";
 | |
|   return os;
 | |
| }
 | |
| 
 | |
| //@}
 | |
| 
 | |
| 
 | |
| #endif
 |