MIDI Pipeline Reference Manual  2.8.3
complex_midi.c
1 /******************************************************************************
2 *******************************************************************************
3 * European Southern Observatory
4 * VLTI MIDI Data Reduction Software
5 *
6 * Module name: complex.c
7 * Description: THIS MODULE CONTAINS ALL COMPLEX ARITHMETIC FUNCTIONS (except assembler ones)
8 *
9 * History:
10 * 03-Feb-03 (jmeisner) Created
11 * 25-Apr-03 (csabet) Added title, directives and included in the MIDI pipeline
12 *******************************************************************************
13 ******************************************************************************/
14 
15 /******************************************************************************
16 * Compiler directives
17 ******************************************************************************/
18 
19 /******************************************************************************
20 * Include files
21 ******************************************************************************/
22 #include <stdio.h>
23 #include <cpl.h>
24 #include <stdlib.h>
25 #include <math.h>
26 #include "complex_midi.h"
27 
28 
29 /*============================ C O D E A R E A ===========================*/
30 struct Complex Czero={0.F, 0.F}; // Available for all apps. DO NOT CHANGE IT!!!!
31 
32 struct Complex Addc(struct Complex z1, struct Complex z2)
33 {
34  struct Complex result;
35  result.r = z1.r + z2.r;
36  result.i = z1.i + z2.i;
37  return result;
38 }
39 
40 struct Complex Subtractc(struct Complex z1, struct Complex z2)
41 {
42  struct Complex result;
43  result.r = z1.r - z2.r;
44  result.i = z1.i - z2.i;
45  return result;
46 }
47 
48 struct Complex Multiplyc(struct Complex z1, struct Complex z2)
49 {
50  struct Complex result;
51  result.r = z1.r*z2.r - z1.i*z2.i;
52  result.i = z1.i*z2.r + z1.r*z2.i;
53  return result;
54 }
55 
56 struct Complex Dividec(struct Complex z1, struct Complex z2)
57 {
58  struct Complex temp;
59 
60  MultiplyConjPtr(&temp, &z1, &z2);
61  return Scalec(temp, 1.F/Cmag2(z2));
62 }
63 
64 
65 // Definitions which act on pointers:
66 
67 void SubtractCptr(struct Complex * result, struct Complex * z1, struct Complex * z2)
68 {
69  result->r = z1->r - z2->r;
70  result->i = z1->i - z2->i;
71 }
72 
73 void AddCptr (struct Complex * result, struct Complex * z1, struct Complex * z2)
74 {
75  result->r = z1->r + z2->r;
76  result->i = z1->i + z2->i;
77 }
78 
79 void MultiplyCptr(struct Complex * result, struct Complex * z1, struct Complex * z2)
80 {
81  float temp;
82  temp=z1->r;
83  result->r = z1->r*z2->r - z1->i*z2->i;
84 // result.i = z1.i*z2.r + z1.r*z2.i; // Old way before pointers passed
85  result->i = z1->i*z2->r + temp*z2->i ;
86 }
87 
88 void MultiplyConjPtr(struct Complex * result, struct Complex * z1, struct Complex * z2)
89 {
90  float temp;
91  temp=z1->r;
92  result->r = z1->r*z2->r + z1->i*z2->i;
93 // result.i = z1.i*z2.r - z1.r*z2.i;
94  result->i = z1->i*z2->r - temp*z2->i;
95 }
96 
97 struct Complex Scalec(struct Complex z, float scale)
98 {
99  struct Complex result;
100  result.r = scale * z.r;
101  result.i = scale * z.i;
102  return result;
103 }
104 
105 struct Complex Unitc(struct Complex z)
106 {
107  double temp;
108 RESTART:
109  temp = z.r*z.r + z.i*z.i;
110  if(temp < .0000000000000000000000000001)
111  {
112  z.r += .00000000000001;
113  goto RESTART;
114  }
115  return Scalec(z, 1.F/sqrt(temp));
116 }
117 
118 float Cmag(struct Complex z)
119 {
120  return (float) sqrt(z.r*z.r + z.i*z.i);
121 }
122 
123 float Cmag2(struct Complex z)
124 {
125  return (z.r*z.r + z.i*z.i);
126 }
127 
128 
129 // New Nov 9, 1999:
130 // Returns a positive real part, if 0 then returns neg imag part.
131 struct Complex Csqrt(struct Complex value)
132 {
133  float mag;
134  struct Complex result;
135 
136  // Special case:
137  if(value.i==0.F)
138  {
139  if(value.r>0)
140  {
141  result.i = 0.F;
142  result.r = (float) sqrt(value.r);
143  return result;
144  }
145  // Else:
146  result.r = 0.F;
147  result.i = -((float) sqrt(-value.r));
148  return result;
149  }
150 
151  mag = Cmag(value);
152  result.r = (float) sqrt(.5*(mag+value.r));
153  result.i = (float) sqrt(.5*(mag-value.r));
154 
155  if(value.i < 0.F)
156  result.i = -result.i;
157 
158  return result;
159 }
160 
161 // Now defined in c:
162 void GetScaledEtoJtimes(float Angle, struct Complex *Result, float scale)
163 {
164  Result->r = scale * (float) cos(Angle);
165  Result->i = scale * (float) sin(Angle);
166 }
167 
168 void GetEtoJtimes(float Angle, struct Complex *Result)
169 {
170  Result->r = (float) cos(Angle);
171  Result->i = (float) sin(Angle);
172 }
173 
174 void GetExpc(struct Complex *Result, struct Complex z)
175 {
176 
177  GetScaledEtoJtimes(z.i, Result, (float) exp(z.r));
178 }
179 
180 struct Complex jtimes(struct Complex z)
181 {
182  struct Complex result;
183  result.i = z.r;
184  result.r = -z.i;
185  return result;
186 }
187 
188 
189 
190 // Richard added on these functions
191 float Arg(struct Complex z)
192 {
193  if(fabs(z.r)<.000000000000000001)
194  if(fabs(z.i)<.000000000000000001)
195  return 0.F;
196 // NAH: if (temp<0) temp = temp + 360.F;
197  return (float) atan2(z.i,z.r);
198 }
199 
200 void printC(struct Complex z)
201 {
202  if(fabs(z.i) < .00001F*fabs(z.r))
203  z.i = 0.F;
204 /***************************************
205  {
206  if(z.r < 0.F)
207  cpl_msg_info(cpl_func,"%.4g + j 0 = %.4g @ 180ø\n", z.r, -z.r);
208  else
209  cpl_msg_info(cpl_func,"%.4g + j 0 = %.4g @ 0ø\n", z.r, z.r);
210  }
211  else
212 ************************************************/
213  cpl_msg_info(cpl_func,"%.4g + j %.4g = %.4g @ %4.1fø\n",
214  z.r,z.i,Cmag(z), 57.2958F*Arg(z));
215 // cpl_msg_info(cpl_func,"real - %.2f imag - %.2f mag - %.2f phi - %.2f\n",
216 }
217 
218 /*****************************************************************************/