Complex.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #ifndef __MATH_COMPLEX_H__
  21. #define __MATH_COMPLEX_H__
  22. /*
  23. ===============================================================================
  24. Complex number
  25. ===============================================================================
  26. */
  27. class idComplex {
  28. public:
  29. float r; // real part
  30. float i; // imaginary part
  31. idComplex();
  32. idComplex( const float r, const float i );
  33. void Set( const float r, const float i );
  34. void Zero();
  35. float operator[]( int index ) const;
  36. float & operator[]( int index );
  37. idComplex operator-() const;
  38. idComplex & operator=( const idComplex &a );
  39. idComplex operator*( const idComplex &a ) const;
  40. idComplex operator/( const idComplex &a ) const;
  41. idComplex operator+( const idComplex &a ) const;
  42. idComplex operator-( const idComplex &a ) const;
  43. idComplex & operator*=( const idComplex &a );
  44. idComplex & operator/=( const idComplex &a );
  45. idComplex & operator+=( const idComplex &a );
  46. idComplex & operator-=( const idComplex &a );
  47. idComplex operator*( const float a ) const;
  48. idComplex operator/( const float a ) const;
  49. idComplex operator+( const float a ) const;
  50. idComplex operator-( const float a ) const;
  51. idComplex & operator*=( const float a );
  52. idComplex & operator/=( const float a );
  53. idComplex & operator+=( const float a );
  54. idComplex & operator-=( const float a );
  55. friend idComplex operator*( const float a, const idComplex &b );
  56. friend idComplex operator/( const float a, const idComplex &b );
  57. friend idComplex operator+( const float a, const idComplex &b );
  58. friend idComplex operator-( const float a, const idComplex &b );
  59. bool Compare( const idComplex &a ) const; // exact compare, no epsilon
  60. bool Compare( const idComplex &a, const float epsilon ) const; // compare with epsilon
  61. bool operator==( const idComplex &a ) const; // exact compare, no epsilon
  62. bool operator!=( const idComplex &a ) const; // exact compare, no epsilon
  63. idComplex Reciprocal() const;
  64. idComplex Sqrt() const;
  65. float Abs() const;
  66. int GetDimension() const;
  67. const float * ToFloatPtr() const;
  68. float * ToFloatPtr();
  69. const char * ToString( int precision = 2 ) const;
  70. };
  71. extern idComplex complex_origin;
  72. #define complex_zero complex_origin
  73. ID_INLINE idComplex::idComplex() {
  74. }
  75. ID_INLINE idComplex::idComplex( const float r, const float i ) {
  76. this->r = r;
  77. this->i = i;
  78. }
  79. ID_INLINE void idComplex::Set( const float r, const float i ) {
  80. this->r = r;
  81. this->i = i;
  82. }
  83. ID_INLINE void idComplex::Zero() {
  84. r = i = 0.0f;
  85. }
  86. ID_INLINE float idComplex::operator[]( int index ) const {
  87. assert( index >= 0 && index < 2 );
  88. return ( &r )[ index ];
  89. }
  90. ID_INLINE float& idComplex::operator[]( int index ) {
  91. assert( index >= 0 && index < 2 );
  92. return ( &r )[ index ];
  93. }
  94. ID_INLINE idComplex idComplex::operator-() const {
  95. return idComplex( -r, -i );
  96. }
  97. ID_INLINE idComplex &idComplex::operator=( const idComplex &a ) {
  98. r = a.r;
  99. i = a.i;
  100. return *this;
  101. }
  102. ID_INLINE idComplex idComplex::operator*( const idComplex &a ) const {
  103. return idComplex( r * a.r - i * a.i, i * a.r + r * a.i );
  104. }
  105. ID_INLINE idComplex idComplex::operator/( const idComplex &a ) const {
  106. float s, t;
  107. if ( idMath::Fabs( a.r ) >= idMath::Fabs( a.i ) ) {
  108. s = a.i / a.r;
  109. t = 1.0f / ( a.r + s * a.i );
  110. return idComplex( ( r + s * i ) * t, ( i - s * r ) * t );
  111. } else {
  112. s = a.r / a.i;
  113. t = 1.0f / ( s * a.r + a.i );
  114. return idComplex( ( r * s + i ) * t, ( i * s - r ) * t );
  115. }
  116. }
  117. ID_INLINE idComplex idComplex::operator+( const idComplex &a ) const {
  118. return idComplex( r + a.r, i + a.i );
  119. }
  120. ID_INLINE idComplex idComplex::operator-( const idComplex &a ) const {
  121. return idComplex( r - a.r, i - a.i );
  122. }
  123. ID_INLINE idComplex &idComplex::operator*=( const idComplex &a ) {
  124. *this = idComplex( r * a.r - i * a.i, i * a.r + r * a.i );
  125. return *this;
  126. }
  127. ID_INLINE idComplex &idComplex::operator/=( const idComplex &a ) {
  128. float s, t;
  129. if ( idMath::Fabs( a.r ) >= idMath::Fabs( a.i ) ) {
  130. s = a.i / a.r;
  131. t = 1.0f / ( a.r + s * a.i );
  132. *this = idComplex( ( r + s * i ) * t, ( i - s * r ) * t );
  133. } else {
  134. s = a.r / a.i;
  135. t = 1.0f / ( s * a.r + a.i );
  136. *this = idComplex( ( r * s + i ) * t, ( i * s - r ) * t );
  137. }
  138. return *this;
  139. }
  140. ID_INLINE idComplex &idComplex::operator+=( const idComplex &a ) {
  141. r += a.r;
  142. i += a.i;
  143. return *this;
  144. }
  145. ID_INLINE idComplex &idComplex::operator-=( const idComplex &a ) {
  146. r -= a.r;
  147. i -= a.i;
  148. return *this;
  149. }
  150. ID_INLINE idComplex idComplex::operator*( const float a ) const {
  151. return idComplex( r * a, i * a );
  152. }
  153. ID_INLINE idComplex idComplex::operator/( const float a ) const {
  154. float s = 1.0f / a;
  155. return idComplex( r * s, i * s );
  156. }
  157. ID_INLINE idComplex idComplex::operator+( const float a ) const {
  158. return idComplex( r + a, i );
  159. }
  160. ID_INLINE idComplex idComplex::operator-( const float a ) const {
  161. return idComplex( r - a, i );
  162. }
  163. ID_INLINE idComplex &idComplex::operator*=( const float a ) {
  164. r *= a;
  165. i *= a;
  166. return *this;
  167. }
  168. ID_INLINE idComplex &idComplex::operator/=( const float a ) {
  169. float s = 1.0f / a;
  170. r *= s;
  171. i *= s;
  172. return *this;
  173. }
  174. ID_INLINE idComplex &idComplex::operator+=( const float a ) {
  175. r += a;
  176. return *this;
  177. }
  178. ID_INLINE idComplex &idComplex::operator-=( const float a ) {
  179. r -= a;
  180. return *this;
  181. }
  182. ID_INLINE idComplex operator*( const float a, const idComplex &b ) {
  183. return idComplex( a * b.r, a * b.i );
  184. }
  185. ID_INLINE idComplex operator/( const float a, const idComplex &b ) {
  186. float s, t;
  187. if ( idMath::Fabs( b.r ) >= idMath::Fabs( b.i ) ) {
  188. s = b.i / b.r;
  189. t = a / ( b.r + s * b.i );
  190. return idComplex( t, - s * t );
  191. } else {
  192. s = b.r / b.i;
  193. t = a / ( s * b.r + b.i );
  194. return idComplex( s * t, - t );
  195. }
  196. }
  197. ID_INLINE idComplex operator+( const float a, const idComplex &b ) {
  198. return idComplex( a + b.r, b.i );
  199. }
  200. ID_INLINE idComplex operator-( const float a, const idComplex &b ) {
  201. return idComplex( a - b.r, -b.i );
  202. }
  203. ID_INLINE idComplex idComplex::Reciprocal() const {
  204. float s, t;
  205. if ( idMath::Fabs( r ) >= idMath::Fabs( i ) ) {
  206. s = i / r;
  207. t = 1.0f / ( r + s * i );
  208. return idComplex( t, - s * t );
  209. } else {
  210. s = r / i;
  211. t = 1.0f / ( s * r + i );
  212. return idComplex( s * t, - t );
  213. }
  214. }
  215. ID_INLINE idComplex idComplex::Sqrt() const {
  216. float x, y, w;
  217. if ( r == 0.0f && i == 0.0f ) {
  218. return idComplex( 0.0f, 0.0f );
  219. }
  220. x = idMath::Fabs( r );
  221. y = idMath::Fabs( i );
  222. if ( x >= y ) {
  223. w = y / x;
  224. w = idMath::Sqrt( x ) * idMath::Sqrt( 0.5f * ( 1.0f + idMath::Sqrt( 1.0f + w * w ) ) );
  225. } else {
  226. w = x / y;
  227. w = idMath::Sqrt( y ) * idMath::Sqrt( 0.5f * ( w + idMath::Sqrt( 1.0f + w * w ) ) );
  228. }
  229. if ( w == 0.0f ) {
  230. return idComplex( 0.0f, 0.0f );
  231. }
  232. if ( r >= 0.0f ) {
  233. return idComplex( w, 0.5f * i / w );
  234. } else {
  235. return idComplex( 0.5f * y / w, ( i >= 0.0f ) ? w : -w );
  236. }
  237. }
  238. ID_INLINE float idComplex::Abs() const {
  239. float x, y, t;
  240. x = idMath::Fabs( r );
  241. y = idMath::Fabs( i );
  242. if ( x == 0.0f ) {
  243. return y;
  244. } else if ( y == 0.0f ) {
  245. return x;
  246. } else if ( x > y ) {
  247. t = y / x;
  248. return x * idMath::Sqrt( 1.0f + t * t );
  249. } else {
  250. t = x / y;
  251. return y * idMath::Sqrt( 1.0f + t * t );
  252. }
  253. }
  254. ID_INLINE bool idComplex::Compare( const idComplex &a ) const {
  255. return ( ( r == a.r ) && ( i == a.i ) );
  256. }
  257. ID_INLINE bool idComplex::Compare( const idComplex &a, const float epsilon ) const {
  258. if ( idMath::Fabs( r - a.r ) > epsilon ) {
  259. return false;
  260. }
  261. if ( idMath::Fabs( i - a.i ) > epsilon ) {
  262. return false;
  263. }
  264. return true;
  265. }
  266. ID_INLINE bool idComplex::operator==( const idComplex &a ) const {
  267. return Compare( a );
  268. }
  269. ID_INLINE bool idComplex::operator!=( const idComplex &a ) const {
  270. return !Compare( a );
  271. }
  272. ID_INLINE int idComplex::GetDimension() const {
  273. return 2;
  274. }
  275. ID_INLINE const float *idComplex::ToFloatPtr() const {
  276. return &r;
  277. }
  278. ID_INLINE float *idComplex::ToFloatPtr() {
  279. return &r;
  280. }
  281. #endif /* !__MATH_COMPLEX_H__ */