00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef __it_cplx_h
00027 #define __it_cplx_h
00028
00029 #include <it/types.h>
00030 #include <math.h>
00031 #include <assert.h>
00032
00033
00034
00035
00036
00037
00038 typedef struct _cplx_ {
00039 double r;
00040 double i;
00041 } cplx;
00042
00043 #define cplx(r, i) { r, i }
00044 #define creal(c) ((c).r)
00045 #define cimag(c) ((c).i)
00046 #define __it_abs(x) (((x)>=0)?(x):(-x))
00047
00048 static inline cplx cadd (cplx a, cplx b) {
00049 cplx r;
00050 r.r = a.r + b.r;
00051 r.i = a.i + b.i;
00052 return (r);
00053 }
00054 static inline cplx csub (cplx a, cplx b) {
00055 cplx r;
00056 r.r = a.r - b.r;
00057 r.i = a.i - b.i;
00058 return (r);
00059 }
00060
00061
00062 static inline cplx cmul (cplx a, cplx b) {
00063 cplx r;
00064 r.r = a.r * b.r - a.i * b.i;
00065 r.i = a.r * b.i + a.i * b.r;
00066
00067 return (r);
00068 }
00069
00070
00071 static inline cplx cscale (cplx a, double b) {
00072 cplx r;
00073 r.r = a.r * b;
00074 r.i = a.i * b;
00075 return (r);
00076 }
00077
00078
00079 static inline cplx cdiv (cplx a, cplx b) {
00080 cplx r;
00081 double q, n;
00082
00083 assert (b.r != 0 || b.i != 0);
00084
00085 if (__it_abs (b.r) < __it_abs (b.i)) {
00086 q = b.r / b.i;
00087 n = b.r * q + b.i;
00088 r.r = (a.r * q + a.i) / n;
00089 r.i = (a.i * q - a.r) / n;
00090 }
00091 else {
00092 q = b.i / b.r;
00093 n = b.i * q + b.r;
00094 r.r = (a.r + a.i * q) / n;
00095 r.i = (a.i - a.r * q) / n;
00096 }
00097
00098 return (r);
00099 }
00100
00101
00102 static inline cplx cconj (cplx a) {
00103 cplx r;
00104 r.r = a.r;
00105 r.i = -a.i;
00106 return (r);
00107 }
00108
00109
00110 static inline cplx cneg (cplx a) {
00111 cplx r;
00112 r.r = -a.r;
00113 r.i = -a.i;
00114 return (r);
00115 }
00116
00117
00118 static inline cplx cinv (cplx a) {
00119 cplx r;
00120 double q, n;
00121
00122 assert (a.r != 0 || a.i != 0);
00123
00124 if (__it_abs (a.r) < __it_abs (a.i)) {
00125 q = a.r / a.i;
00126 n = a.r * q + a.i;
00127 r.r = q / n;
00128 r.i = -1.0 / n;
00129 }
00130 else {
00131 q = a.i / a.r;
00132 n = a.i * q + a.r;
00133 r.r = 1.0 / n;
00134 r.i = -q / n;
00135 }
00136
00137 return (r);
00138 }
00139
00140 static inline int ceq (cplx a, cplx b) {
00141 return (a.r == b.r && a.i == b.i);
00142 }
00143
00144
00145 static inline double cnorm (cplx a) {
00146 double q;
00147
00148 a.r = __it_abs (a.r);
00149 a.i = __it_abs (a.i);
00150
00151 if (!(a.r + a.i))
00152 return (0);
00153
00154 if (a.r < a.i) {
00155 q = a.r / a.i;
00156 return (a.i * sqrt (1 + q * q));
00157 }
00158 else {
00159 q = a.i / a.r;
00160 return (a.r * sqrt (1 + q * q));
00161 }
00162 }
00163
00164
00165
00166 static inline double cang (cplx a) {
00167 double theta;
00168
00169 if (a.r == 0 && a.i == 0)
00170 return (0);
00171
00172 if (a.r == 0) {
00173 if (a.i > 0)
00174 return (M_PI / 2);
00175 else
00176 return (-M_PI / 2);
00177 }
00178
00179 theta = atan (a.i / a.r);
00180 if (a.r < 0) {
00181 if (a.i < 0)
00182 theta -= M_PI;
00183 else
00184 theta += M_PI;
00185 }
00186
00187 return theta;
00188 }
00189
00190
00191
00192 #ifdef ARCH_HAS_SSE
00193 static inline void __cplx_swap_sse (cplx * a, cplx * b) {
00194 asm volatile ("movq (%0),%%xmm0\n"
00195 "movq (%1),%%xmm1\n"
00196 "movq %%xmm0,(%1)\n"
00197 "movq %%xmm1,(%0)\n"::"r" (a), "r" (b):"memory");
00198 }
00199 #define cplx_swap(a, b) __cplx_swap_sse(&a, &b)
00200 #else
00201 static inline void __cplx_swap (cplx * a, cplx * b) {
00202 double t0, t1;
00203 t0 = a->r;
00204 t1 = a->i;
00205 a->r = b->r;
00206 a->i = b->i;
00207 b->r = t0;
00208 b->i = t1;
00209 }
00210 #define cplx_swap(a, b) __cplx_swap(&a, &b)
00211 #endif
00212
00213
00214 extern cplx const cplx_0;
00215 extern cplx const cplx_1;
00216 extern cplx const cplx_I;
00217 #define cplx_zero cplx_0
00218 #define cplx_one cplx_1
00219
00220
00221
00222
00223 #endif