include/it/cplx.h

Go to the documentation of this file.
00001 /*
00002    libit - Library for basic source and channel coding functions
00003    Copyright (C) 2005-2008 Francois Cayre, Vivien Chappelier, Herve Jegou
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public
00016    License along with this library; if not, write to the Free
00017    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 */
00019 
00020 /*
00021   Complex type
00022   Copyright (C) 2005 Vivien Chappelier
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 /*! \defgroup cplx Complex type                                              */
00035 /* @{                                                                        */
00036 /*---------------------------------------------------------------------------*/
00037 
00038   typedef struct _cplx_ {
00039     double r;     /* real part      */
00040     double i;     /* imaginary part */
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 /* scale a complex by a real number */
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 /* return the modulus of a complex */
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 /* return the argument of a complex in ]-pi;pi] */
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 /* swap two complex numbers */
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 /* some constants */
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

Hosted by
Copyright (C) 2005-2006 Hervé Jégou
Vivien Chappelier
Francois Cayre
libit logo courtesy of Jonathan Delhumeau