⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cx.cpp

📁 VC环境下的实用的复数库函数,编译后可作为库函数使用.
💻 CPP
字号:
#define WANT_MATH
#define WANT_STREAM

#include "cx.h"

#ifdef use_namespace
namespace RBD_COMPLEX {
#endif


ImaginaryUnit _I_;

Real pi, pi_times_2, pi_over_2, pi_over_4;


Real CX::cabs() const
{
   // reduce chances of floating point overflow

   Real x = ::fabs(X); Real y = ::fabs(Y);
   if (x > y) { Real r = y / x; return x * ::sqrt(1.0 + r * r); }
   else if (y == 0) return 0;
   else { Real r = x / y; return y * ::sqrt(1.0 + r * r); }
}

Real CX::arg() const { return atan2(Y, X); }

Real Imag::arg() const
   { return (Y > 0.0) ? pi_over_2 : (Y < 0.0) ? - pi_over_2 : 0; }


CX operator/(const CX& w1, const CX& w2)
{
   // reduce chances of floating point overflow
   if (::fabs(w2.X)>=::fabs(w2.Y))
   {
      Real r = w2.Y/w2.X; Real d = w2.X * (1.0 + r * r);
      return CX( (w1.X+w1.Y*r)/d, (w1.Y-w1.X*r)/d );
   }
   else
   {
      Real r = w2.X/w2.Y; Real d = w2.Y * (1.0 + r * r);
      return CX( (w1.X*r+w1.Y)/d, (w1.Y*r-w1.X)/d );
   }
}

CX operator/(Real x1, const CX& w)
{
   if (::fabs(w.X) >= ::fabs(w.Y))
   {
      Real r = w.Y/w.X; Real d = x1 / (w.X * (1.0 + r * r));
      return CX( d, -d*r );
   }
   else
   {
      Real r = w.X/w.Y; Real d = x1 / (w.Y * (1.0 + r * r));
      return CX( d*r, -d );
   }
}

CX operator/(Imag y1, const CX& w)
{
   if (::fabs(w.X) >= ::fabs(w.Y))
   {
      Real r = w.Y/w.X; Real d = y1.Y / (w.X * (1.0 + r * r));
      return CX( d*r, d );
   }
   else
   {
      Real r = w.X/w.Y; Real d = y1.Y / (w.Y * (1.0 + r * r));
      return CX( d, d*r );
   }
}

CX operator/(ImaginaryUnit, const CX& w)
{
   if (::fabs(w.X) >= ::fabs(w.Y))
   {
      Real r = w.Y/w.X; Real d = 1.0 / (w.X * (1.0 + r * r));
      return CX( d*r, d );
   }
   else
   {
      Real r = w.X/w.Y; Real d = 1.0 / (w.Y * (1.0 + r * r));
      return CX( d, d*r );
   }
}


CX exp(const CX& z) { return ::exp(z.X) * CX(::cos(z.Y), ::sin(z.Y)); }


CX log(const CX& z)
   { return CX(0.5 * ::log(z.X*z.X+z.Y*z.Y), ::atan2(z.Y,z.X)); }

CX sqrt(const CX& z)
{
   Real x = ::fabs(z.X); Real y = ::fabs(z.Y);
   if (x > y)
   {
      Real r = y / x; Real s = ::sqrt(1.0 + r * r) + 1.0;
      x = ::sqrt(x * s / 2); y = ::sqrt(y * r / (s * 2));
   }
   else if (y == 0) return CX(0, 0);
   else
   {
      Real r = x / y; Real s = ::sqrt(1.0 + r * r) + r;
      x = ::sqrt(y * s / 2); y = ::sqrt(y / (s * 2));
   }
   if (z.Y >= 0) { if (z.X >= 0) return CX(x, y); else return CX(y, x); }
   else { if (z.X >= 0) return CX(x, -y); else return CX(y, -x); }
}

CX sin(const CX& z)
   { return CX(::sin(z.X) * ::cosh(z.Y), ::cos(z.X) * ::sinh(z.Y)); }

CX cos(const CX& z)
   { return CX(::cos(z.X) * ::cosh(z.Y), - ::sin(z.X) * ::sinh(z.Y)); }

CX tan(const CX& z)
   { return CX(::tan(z.X), ::tanh(z.Y)) / CX(1, -::tan(z.X) * ::tanh(z.Y)); }

CX sinh(const CX& z) { return sin(_I_ * z) / _I_; }

CX cosh(const CX& z) { return cos(_I_ * z); }

CX tanh(const CX& z) { return tan(_I_ * z) / _I_; }



CX exp(Imag z) { return CX(::cos(z.Y), ::sin(z.Y)); }

CX log(Imag z)
{
   if (z.Y > 0.0) return CX(::log(z.Y), pi_over_2);
   else return CX(::log(-z.Y), -pi_over_2);
}

CX sqrt(Imag y)
{
   if (y.Y >= 0) { Real sy = ::sqrt(y.Y / 2.0); return CX(sy, sy); }
   else { Real sy = ::sqrt(-y.Y / 2.0); return CX(sy, -sy); }
}

CX pow(const CX& z, int n2)
{
   switch (n2)
   {
   case 0: return CX(1.0);
   case 1: return z;
   case 2: return square(z);
   case 3: return square(z) * z;
   case 4: { CX z2 = square(z); return square(z2); }
   case 5: { CX z2 = square(z); return square(z2) * z; }
   case 6: { CX z2 = square(z); return square(z2) * z2; }
   case 7: { CX z2 = square(z); return square(z2) * z2 * z; }
   case 8:
      { CX z2 = square(z); CX z4 = square(z2); return square(z4); }
   case 9:
      { CX z2 = square(z); CX z4 = square(z2); return square(z4) * z; }
   case 10:
      { CX z2 = square(z); CX z4 = square(z2); return square(z4) * z2; }
   case 11:
      { CX z2 = square(z); CX z4 = square(z2); return square(z4) * z2 * z; }
   case 12:
      { CX z2 = square(z); CX z4 = square(z2); return square(z4) * z4; }
   default:
      if (n2 < 0 && n2 >= -12)
      {
         if (z == 0)
            Throw(Runtime_error("pow: first arg 0, second (integer) arg < 0"));
         return pow(1.0 / z, -n2);
      }
      return pow(z, (Real)n2);
   }
}

CX pow(const CX& z1, Real r2)
{
   if (z1 == 0)
   {
      if (r2 > 0) return 0.0;
      else
         Throw(Runtime_error("pow: first arg 0, second arg real part <= 0"));
   }
   return exp(r2 * log(z1));
}

CX pow(const CX& z1, Imag y2)
{
   if (z1 == 0)
      Throw(Runtime_error("pow: first arg 0, second arg imaginary"));
   return exp(y2 * log(z1));
}

CX pow(const CX& z1, const CX& z2)
{
   if (z1 == 0)
   {
      if (z2.X > 0) return 0.0;
      else
         Throw(Runtime_error("pow: first arg 0, second arg real part <= 0"));
   }
   return exp(z2 * log(z1));
}

CX pow(Real r1, const CX& z2)
{
   if (r1 == 0)
   {
      if (z2.X > 0) return 0.0;
      else
         Throw(Runtime_error("pow: first arg 0, second arg real part <= 0"));
   }
   else if (r1 > 0) return exp(z2 * ::log(r1));
   return exp(z2 * (_I_ * pi + ::log(-r1)));
}

CX pow(Imag y1, const CX& z2)
{
   if (y1 == 0)
   {
      if (z2.X > 0) return 0.0;
      else
         Throw(Runtime_error("pow: first arg 0, second arg real part <= 0"));
   }
   return exp(z2 * log(y1));
}

CX pow(Imag y1, int n2)
{
   Real R = ipow(y1.Y, n2);
   int RA = (n2 >= 0) ? n2 & 3 : (4 - ((-n2) & 3)) & 3;
   switch (RA)
   {
   case 0: return CX(R);
   case 1: return CX(0,R);
   case 2: return CX(-R);
   case 3: return CX(0,-R);
   }
   return 0;
}


CX pow(Imag y1, Real r2)
{
   if (y1 == 0)
   {
      if (r2 > 0) return 0.0;
      else
         Throw(Runtime_error("pow: first arg 0, second arg real part <= 0"));
   }
   return exp(r2 * log(y1));
}

CX pow(Imag y1, Imag y2)
{
   if (y1 == 0)
      Throw(Runtime_error("pow: first arg 0, second arg imaginary"));
   return exp(y2 * log(y1));
}

CX pow(Real r1, Imag y2)
{
   if (r1 == 0)
      Throw(Runtime_error("pow: first arg 0, second arg imaginary"));
   else if (r1 > 0) return exp(y2 * ::log(r1));
   return exp(y2 * (_I_ * pi + ::log(-r1)));
}



// won't need this when integer version of pow is available

Real ipow(Real x, int n)
{
   switch (n)
   {
   case 0:  return 1.0;
   case 1:  return x;
   case 2:  return x*x;
   case 3:  return x*x*x;
   case 4:  { Real x2 = x*x; return x2*x2; }
   case 5:  { Real x2 = x*x; return x2*x2 * x; }
   case 6:  { Real x2 = x*x; return x2*x2 * x2; }
   case 7:  { Real x2 = x*x; return x2*x2 * x2 * x; }
   case 8:  { Real x2 = x*x; Real x4 = x2*x2; return x4*x4; }
   case 9:  { Real x2 = x*x; Real x4 = x2*x2; return x4*x4 * x; }
   case 10: { Real x2 = x*x; Real x4 = x2*x2; return x4*x4 * x2; }
   case 11: { Real x2 = x*x; Real x4 = x2*x2; return x4*x4 * x2 * x; }
   case 12: { Real x2 = x*x; Real x4 = x2*x2; return x4*x4 * x4; }
   default:
      if (n < 0 && n >= -12) return ipow(1.0 / x, -n);
      return ::pow(x, (Real)n);
   }
}

ComplexPackageInitialise::ComplexPackageInitialise()
{
   if ( !pi)
   {
      pi = 3.141592653589793238462643;
      pi_times_2 = pi * 2;
      pi_over_2 = pi / 2;
      pi_over_4 = pi / 4;
   }
}


#ifdef use_namespace
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -