1. /* scomplex.h by K.Tsuru */
  2. /*********************************************************
  3. SN library
  4. SComplex class
  5. It provides a multi-precision complex number arithmetic.
  6. I referred to two styles.
  7. (a) gcc's "complex"
  8. friend SComplex& ccmult(SComplex* ths, const SComplex& z);
  9. (b) B.Stroustrup "The C++ Programming Language Third Edition"
  10. first operator *=() is defined
  11. second operator *(a, b)
  12. I paied attention to
  13. 1.copy constructor is heavy and spends memory.
  14. 2.I want to use statements &x == &y in the operator x == y to speed-up.
  15. Almost part has been rewritten in ver.2.18.
  16. *********************************************************/
  17. #ifndef SCOMPLEX_H
  18. #define SCOMPLEX_H
  19. #ifndef SN_H
  20. #include "sn.h"
  21. #endif
  22. class SComplex {
  23. private:
  24. SDouble re, im;
  25. /********* List of unusable functions which have no body.******/
  26. SComplex operator>(const SComplex&) const;
  27. SComplex operator>=(const SComplex&) const;
  28. SComplex operator<(const SComplex&) const;
  29. SComplex operator<=(const SComplex&) const;
  30. public:
  31. // default constructor do nothing. For large size array declaration.
  32. SComplex() {} // "re" and "im" are not initialized and occupy no memory.
  33. // constructor by single SDouble values
  34. // No "explicit" causes (SD Op SD) error
  35. // Cannot use "SComplex c = x;"(NG) instead of "SComplex c(x);"(OK).
  36. explicit SComplex(const SDouble& rp) : re(rp), im(0.0){}
  37. // constructor by two SDouble values
  38. SComplex(const SDouble& rp, const SDouble& ip) : re(rp), im(ip){}
  39. // constructor by two double values since ver 2.18
  40. // This enables us to use "return 0.0".
  41. SComplex(double rp, double ip = 0.0) : re(rp), im(ip){}
  42. // default copy constructor is used according to refference (b)
  43. // SComplex(const SComplex& z) :re(z.re), im(z.im){}
  44. SComplex(const complex<double>& z) :re(z.real()), im(z.imag()){}
  45. ~SComplex(){}
  46. SDouble Real() const { return re;} // real part
  47. SDouble Imag() const { return im;} // imaginary part
  48. SDouble Norm() const; // an inline function defined below
  49. SComplex Conj() const { return SComplex(re, -im); }
  50. // multiple of i or -i
  51. SComplex& MultI() { im.ChangeSign(9401); std::swap(re, im); return *this; } // i*z
  52. SComplex& MultMI() { re.ChangeSign(9402); std::swap(re, im); return *this; } // -i*z = z/i
  53. uint Head() const { return min( re.Head(), im.Head() ); }
  54. uint Tail() const { return min( re.Tail(), im.Tail() ); }
  55. uint reHead() const { return re.Head(); }
  56. uint reTail() const { return re.Tail(); }
  57. uint imHead() const { return im.Head(); }
  58. uint imTail() const { return im.Tail(); }
  59. void FigureClear(uint from, uint to) {
  60. re.FigureClear(from, to); im.FigureClear(from, to);
  61. }
  62. void SetInt(int i) { re.SetInt(i); im.SetZero(); }
  63. void SetZero(){ re.SetZero(); im.SetZero(); }
  64. void ChangeSign(int id = 91){ // z -> -z
  65. re.ChangeSign(id); im.ChangeSign(id);
  66. }
  67. // If you want to change the real part only, use such as z.Set(newValue, z.Imag());
  68. // The statement im = z.Imag(); does not copy, because &im == &ip.
  69. void Set(const SDouble& rp, const SDouble& ip) { re = rp; im = ip; }
  70. bool IsZero(int id=90) const { return (re.Sign(id) == 0) && (im.Sign(id) == 0); }
  71. //sign operators
  72. SComplex operator+() const { return *this; }
  73. SComplex operator-() const;
  74. //Operators whose rhs is scalar.
  75. // SComplex& operator=(const SDouble& x); // SD Op SD error
  76. SComplex& operator+=(const SDouble& x);
  77. SComplex& operator-=(const SDouble& x);
  78. SComplex& operator*=(const SDouble& x);
  79. SComplex& operator/=(const SDouble& x);
  80. /****** mixed-mode operations with double since ver 2.18 ******/
  81. // SComplex& operator=(double x);
  82. SComplex& operator+=(double x);
  83. SComplex& operator-=(double x);
  84. SComplex& operator*=(double x);
  85. SComplex& operator/=(double x);
  86. //Operators whose rhs is complex object.
  87. SComplex& operator=(const SComplex& z);
  88. SComplex& operator=(const complex<double>& z);
  89. SComplex& operator+=(const SComplex& z);
  90. SComplex& operator-=(const SComplex& z);
  91. SComplex& operator*=(const SComplex& z); // 903
  92. SComplex& operator/=(const SComplex& z); // 904
  93. // Multiplication by a small integer.
  94. SComplex& CsMult(ulong n);
  95. // Division by small integer.
  96. SComplex& CsDiv(ulong n);
  97. /*
  98. At the present time it does not support reading from file.
  99. Please use SDouble class' Put(s) and write/read the real and imaginary parts, separately.
  100. Due to the value of "fmt" it outputs in the following form.
  101. iFMT : (real part)[+|-]i*(imaginary part)
  102. BracketFMT : (real part, imaginary part)
  103. midCR : put crlf between real and imaginary part or not
  104. endCR : put crlf at line end or not
  105. */
  106. enum { iFMT = 64, BracketFMT = 128, MID_CR = 256, END_CR = 512};
  107. long Put(int fmt= MID_CR|iFMT) const; // 900 change since ver.2.21
  108. long Puts(int fmt = MID_CR|iFMT) const{ return Put(fmt|END_CR); }
  109. friend ostream& operator<<(ostream& os, const SComplex& sl); // added since version 2.21 902
  110. static int scLineFormat; // set by BRACKET | MID_CR| END_CR
  111. static void SetFormat(int fmt);
  112. static long ioCount;
  113. };
  114. SComplex SetComplex(const char* s); // set SComplex value by (rp,ip).() is not necessary Use delimiter ',' only.
  115. istream& operator>>(istream& s, SComplex& a); // added since version 2.21 903
  116. ///// Cautions : All functions having its body must be "inline".///////
  117. /**********************************
  118. * Implementation of member functions
  119. ***********************************/
  120. inline SDouble SComplex::Norm() const {
  121. return ( re * re + im * im );
  122. }
  123. inline SComplex SComplex::operator-() const {
  124. SComplex z(*this);
  125. z.re = -z.re; z.im = -z.im;
  126. return z;
  127. }
  128. ////// Operators whose rhs is real scalar. //////
  129. inline SComplex& SComplex::operator+=(const SDouble& x) {
  130. re += x; return *this;
  131. }
  132. inline SComplex& SComplex::operator-=(const SDouble& x) {
  133. re -= x; return *this;
  134. }
  135. inline SComplex& SComplex::operator*=(const SDouble& x) {
  136. re *= x; im *= x; return *this;
  137. }
  138. inline SComplex& SComplex::operator/=(const SDouble& x) {
  139. re /= x; im /= x; return *this;
  140. }
  141. /****** Conversion SDouble to SComplex *******************/
  142. /****************************
  143. Cannot use SC+SD because SC + SD yeilds an error as [Notes]candidates are: operator+() const ... MinGW gcc 4.8.1
  144. Please use SC + SComplex(SD, 0.0); or below
  145. ******************************/
  146. inline SComplex SDtoSC(const SDouble& x) {
  147. return SComplex(x, 0.0);
  148. }
  149. inline SComplex SDtoISC(const SDouble& x) {
  150. return SComplex(0.0, x); // i*x
  151. }
  152. /****** mixed-mode operations with double since ver 2.18 ******/
  153. /*
  154. inline SComplex& SComplex::operator=(double x) {
  155. re = x; im = 0.0; return *this;
  156. }
  157. */
  158. inline SComplex& SComplex::operator+=(double x) {
  159. re += x; return *this;
  160. }
  161. inline SComplex& SComplex::operator-=(double x) {
  162. re -= x; return *this;
  163. }
  164. inline SComplex& SComplex::operator*=(double x) {
  165. re *= x; im *= x; return *this;
  166. }
  167. inline SComplex& SComplex::operator/=(double x) {
  168. re /= x; im /= x; return *this;
  169. }
  170. ///// Operators whose rhs is complex object. /////
  171. inline SComplex& SComplex::operator=(const complex<double>& z) {
  172. re = z.real(); im = z.imag();
  173. return *this;
  174. }
  175. // substitution operator SC=SC
  176. inline SComplex& SComplex::operator=(const SComplex& z) { // default is not enough
  177. if(this == &z) return *this; // z = z;
  178. re = z.re; im = z.im;
  179. return *this;
  180. }
  181. inline SComplex& SComplex::operator+=(const SComplex& z) {
  182. re += z.re; im += z.im;
  183. return *this;
  184. }
  185. inline SComplex& SComplex::operator-=(const SComplex& z) {
  186. re -= z.re; im -= z.im;
  187. return *this;
  188. }
  189. /******* Non member functions in the following *******/
  190. //// Two term operators /////
  191. //// plus operators x + y
  192. //// for MIXED_OPERATIONS_WITH_SD see below
  193. //// plus operator x + y
  194. inline SComplex operator+(const SComplex& x, const SComplex& y) {
  195. return SComplex(x.Real() + y.Real(), x.Imag() + y.Imag());
  196. }
  197. //// minus operator x - y
  198. inline SComplex operator-(const SComplex& x, const SComplex& y) {
  199. return SComplex(x.Real() - y.Real(), x.Imag() - y.Imag());
  200. }
  201. //// multiplication operator x * y
  202. inline SComplex operator*(const SComplex& x, const SComplex& y) {
  203. SComplex r = x;
  204. return r *= y;
  205. }
  206. //// division operator x / y
  207. inline SComplex operator/(const SComplex& x, const SComplex& y) {
  208. SComplex r = x;
  209. return r /= y;
  210. }
  211. // Multiplication by a small integer.
  212. inline SComplex& SComplex::CsMult(ulong n) {
  213. if(n) {
  214. re = DsMult(re, n); im = DsMult(im, n);
  215. } else SetZero();
  216. return *this;
  217. }
  218. inline SComplex CsMult(const SComplex& z, ulong n) {
  219. SComplex r = z;
  220. return r.CsMult(n);
  221. }
  222. // Division by a small integer.
  223. inline SComplex& SComplex::CsDiv(ulong n) {
  224. re = DsDiv(re, n); im = DsDiv(im, n);
  225. return *this;
  226. }
  227. inline SComplex CsDiv(const SComplex& z, ulong n) {
  228. SComplex r = z;
  229. return r.CsDiv(n);
  230. }
  231. /****** mixed-mode operations with double since ver 2.18 ******/
  232. inline SComplex operator+(const SComplex& x, double d) { // SC + d
  233. return SComplex(x.Real() + d, x.Imag());
  234. }
  235. inline SComplex operator+(double d, const SComplex& y) { // d + SC
  236. return SComplex(d + y.Real(), y.Imag());
  237. }
  238. inline SComplex operator-(const SComplex& x, double d) { // SC - d
  239. return SComplex(x.Real() - d, x.Imag());
  240. }
  241. inline SComplex operator-(double d, const SComplex& y) { // d - SC
  242. return SComplex(d - y.Real(), -y.Imag());
  243. }
  244. inline SComplex operator*(const SComplex& x, double d) { // SC * d
  245. return SComplex(x.Real() * d, x.Imag() * d);
  246. }
  247. inline SComplex operator*(double d, const SComplex& y) { // d * SC
  248. return SComplex(d * y.Real(), d * y.Imag());
  249. }
  250. inline SComplex operator/(const SComplex& x, double d) { // SC / d
  251. return SComplex(x.Real() / d, x.Imag() / d);
  252. }
  253. inline SComplex operator/(double x, const SComplex& y) { // d / SC
  254. SComplex r = x;
  255. return r /= y;
  256. }
  257. /*****************
  258. basic functions
  259. ******************/
  260. //// relational operators
  261. inline bool operator==(const SComplex& x, const SComplex& y){
  262. return (x.Real()==y.Real()) && (x.Imag()==y.Imag());
  263. }
  264. inline bool operator!=(const SComplex& x, const SComplex& y){
  265. return !(x == y);
  266. }
  267. ///// using binary splitting method ////////
  268. SComplex CpolarBS(const SDouble& r, const SDouble& x); // r*{cos(x)+i*sin(x)}; 9120
  269. SComplex CexpBS(const SComplex& z); // exp(z) 9121
  270. SComplex CcosBS(const SComplex& z); // cos z 9121
  271. SComplex CsinBS(const SComplex& z); // sin z 9122
  272. SComplex CtanBS(const SComplex& z); // tan z 9123
  273. static const SComplex IU(0.0, 1.0); // i (imaginary unit)
  274. static const SComplex MI(0.0, -1.0); // 1/i = -i
  275. ////////////////////////////////////////////////////////////////////////////////////
  276. // For reference in the following
  277. #define MIXED_OPERATIONS_WITH_SD 0
  278. #if MIXED_OPERATIONS_WITH_SD
  279. /*
  280. These operators causes error for 1 + SD etc.
  281. because candidates are : SD op SD and SC op SC.
  282. Then set 0 above.
  283. Please use "+=", etc. operator in {} below.
  284. */
  285. inline SComplex& SComplex::operator=(const SDouble& x) {
  286. re = x; im = 0.0; return *this;
  287. }
  288. inline SComplex operator+(const SComplex& x, const SDouble& y) { // SC + SD
  289. SComplex r = x;
  290. return r += y;
  291. }
  292. inline SComplex operator+(const SDouble& x, const SComplex& y) { // SD + SC
  293. SComplex r = y;
  294. return r += x;
  295. }
  296. inline SComplex operator-(const SComplex& x, const SDouble& y) {
  297. SComplex r = x;
  298. return r -= y;
  299. }
  300. inline SComplex operator-(const SDouble& x, const SComplex& y) {
  301. SComplex r(x, 0.0);
  302. return r -= y;
  303. }
  304. inline SComplex operator*(const SComplex& x, const SDouble& y) {
  305. SComplex r = x;
  306. return r *= y;
  307. }
  308. inline SComplex operator*(const SDouble& x, const SComplex& y) {
  309. SComplex r = y;
  310. return r *= x;
  311. }
  312. inline SComplex operator/(const SComplex& x, const SDouble& y) {
  313. SComplex r = x;
  314. return r /= y;
  315. }
  316. inline SComplex operator/(const SDouble& x, const SComplex& y) {
  317. SComplex r(x, 0.0);
  318. return r /= y;
  319. }
  320. #endif // MIXED_OPERATIONS_WITH_SD
  321. ////////////////////////////////////////////////////////////////////////////////////
  322. #endif //SCOMPLEX_H

scomplex.h : last modifiled at 2017/06/14 20:43:01(12,127 bytes)
created at 2016/04/11 11:18:59
The creation time of this html file is 2017/10/11 16:07:52 (Wed Oct 11 16:07:52 2017).