comparison m-toolbox/test/new_ltf_code/ltf_plan.c @ 0:f0afece42f48

Import.
author Daniele Nicolodi <nicolodi@science.unitn.it>
date Wed, 23 Nov 2011 19:22:13 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f0afece42f48
1
2 /*
3
4 indent ltf_plan.c && \
5 gcc -g -O9 -ffast-math -Wconversion -Wall -W -o ltf_plan ltf_plan.c -lm && \
6 ./ltf_plan > plan.tex
7
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <math.h>
13 #include <assert.h>
14 #include <complex.h>
15
16 #define TEX 0
17
18 struct ltf_plan_one_t
19 {
20 double f; /* frequency at bin center [Hz] */
21 double fres; /* frequency resolution (bin width) [Hz] */
22 double bin; /* bin number (possibly non-integer) */
23 unsigned dftlen; /* length of one DFT segment */
24 unsigned nseg; /* number of DFT segments */
25 unsigned *segstart; /* starting position of each of the nseg segments */
26 };
27 typedef struct ltf_plan_one_t ltf_plan_one;
28
29 struct ltf_plan_t
30 {
31 /* copy of input data */
32 unsigned ndata; /* total number of input data */
33 double fsamp; /* sampling frequency [Hz] */
34 double ovlap; /* window overlap in % */
35 double binmin; /* smallest bin-number to use */
36 unsigned mindftlen; /* minimum length of one segment */
37 unsigned freqdes; /* desired number of frequencies */
38 unsigned avgdes; /* desired number of averages */
39
40 /* scheduler results */
41 unsigned nfreq; /* final number of frequencies */
42 unsigned maxdftlen; /* maximal length of one DFT segment */
43 unsigned maxnseg; /* maximal number of averages */
44 ltf_plan_one *fplan; /* detailed plan for each of nfreq frequencies */
45 };
46 typedef struct ltf_plan_t ltf_plan;
47
48 void
49 gerror (const char *err)
50 {
51 fprintf (stderr, "\n*** Error: %s\n", err);
52 exit (1);
53 }
54
55 int
56 myround (double x)
57 {
58 return ((int) (floor (x + 0.5)));
59 }
60
61
62 void
63 ltf_plan_alloc (ltf_plan * p, unsigned size)
64 {
65 char err[160];
66
67 p->fplan = realloc (p->fplan, size * sizeof (ltf_plan_one));
68
69 if (p->fplan == NULL)
70 {
71 sprintf (err,
72 "ltf_plan: error in allocating %u*%u=%u bytes for p.fplan",
73 size, sizeof (ltf_plan_one), size * sizeof (ltf_plan_one));
74 gerror (err);
75 }
76 }
77
78 ltf_plan
79 plan (unsigned ndata, double fsamp, double ovlap, double binmin,
80 unsigned mindftlen, unsigned freqdes, unsigned avgdes,
81 unsigned getsegstart)
82 {
83 ltf_plan p;
84 ltf_plan_one *p1;
85 double fmin, fmax, fres, f;
86 unsigned j, k, dftlen, segstartpos;
87 double bin;
88 unsigned nseg;
89 double xov;
90 double freslim, fresmin;
91 unsigned nalloc;
92 char err[160];
93 double logfact;
94 unsigned nsegstart; /* number of segstart entries */
95 unsigned *segstartmemory; /* begin of segstart entries */
96 double segincr;
97
98 if (ndata < 500)
99 {
100 sprintf (err, "ltf_plan: illegal value for ndata: %u<500", ndata);
101 gerror (err);
102 }
103
104 if (ndata < 500)
105 {
106 sprintf (err, "ltf_plan: illegal value for ndata: %u<500", ndata);
107 gerror (err);
108 }
109
110 if (fsamp <= 0)
111 {
112 sprintf (err, "ltf_plan: illegal value for fsamp: %g<=0", fsamp);
113 gerror (err);
114 }
115
116 if (binmin < 0)
117 {
118 sprintf (err, "ltf_plan: illegal value for binmin: %g<0", binmin);
119 gerror (err);
120 }
121
122 if (ovlap < 0)
123 {
124 sprintf (err, "ltf_plan: illegal value for ovlap: %g<=0", ovlap);
125 gerror (err);
126 }
127
128 if (ovlap > 99)
129 {
130 sprintf (err, "ltf_plan: illegal value for ovlap: %g>99%%", ovlap);
131 gerror (err);
132 }
133
134 if (freqdes < 3)
135 {
136 sprintf (err, "ltf_plan: illegal value for freqdes: %u<3", freqdes);
137 gerror (err);
138 }
139
140 if (freqdes > ndata / 2)
141 {
142 sprintf (err, "ltf_plan: illegal value for freqdes: %u>%u", freqdes,
143 ndata / 2);
144 gerror (err);
145 }
146
147 /* copy input data */
148 p.ndata = ndata;
149 p.fsamp = fsamp;
150 p.ovlap = ovlap;
151 if (binmin < 1)
152 binmin = 1;
153 p.binmin = binmin;
154 p.mindftlen = mindftlen;
155 p.freqdes = freqdes;
156 p.avgdes = avgdes;
157 p.maxdftlen = p.maxnseg = 0;
158 nsegstart = 0;
159
160 xov = (1. - ovlap / 100.);
161 fmin = fsamp / ndata * binmin;
162 fmax = fsamp / 2;
163 fresmin = fsamp / (double) ndata; /* absolute minimal allowed frequency resolution */
164 freslim = fresmin * (1 + xov * (avgdes - 1)); /* limit above which fres leads to desired number of averages */
165 logfact = (pow (ndata / 2., 1. / freqdes) - 1.);
166
167 /* initial allocation */
168 p.fplan = NULL;
169 nalloc = freqdes;
170 ltf_plan_alloc (&p, nalloc);
171
172 for (j = 0, f = fmin; f < fmax; j++)
173 {
174 if (j >= nalloc)
175 {
176 /* enlarge allocation */
177 nalloc *= 2;
178 ltf_plan_alloc (&p, nalloc);
179 }
180
181 p1 = &(p.fplan[j]);
182
183 fres = f * logfact;
184 fres = (fres > freslim) ? fres : sqrt (fres * freslim);
185 if (fres < fresmin)
186 fres = fresmin;
187
188 bin = (f / fres);
189 if (bin < binmin)
190 {
191 bin = binmin;
192 fres = f / bin;
193 }
194
195 dftlen = myround (fsamp / fres);
196 if (dftlen > ndata)
197 dftlen = ndata;
198 if (dftlen < mindftlen)
199 dftlen = mindftlen;
200 nseg = myround (((double) (ndata - dftlen) /
201 (xov * (double) dftlen)) + 1);
202 if (nseg == 1)
203 dftlen = ndata;
204
205 fres = fsamp / dftlen;
206 bin = f / fres;
207
208 p1->f = f;
209 p1->fres = fres;
210 p1->bin = bin;
211 p1->dftlen = dftlen;
212 p1->nseg = nseg;
213 if (nseg > p.maxnseg)
214 p.maxnseg = nseg;
215 nsegstart += nseg;
216 if (dftlen > p.maxdftlen)
217 p.maxdftlen = dftlen;
218 f += fres;
219 }
220 p.nfreq = j;
221 /* allocation shrink to fit */
222 nalloc = p.nfreq;
223 ltf_plan_alloc (&p, nalloc);
224
225 /* determine starting indices of DFT segments */
226 if (!getsegstart)
227 {
228 for (j = 0; j < p.nfreq; j++)
229 p.fplan[j].segstart = NULL;
230 }
231 else
232 {
233 segstartmemory = malloc (nsegstart * sizeof (unsigned));
234 if (segstartmemory == NULL)
235 {
236 sprintf (err,
237 "ltf_plan: error allocating %u bytes for segment start indices",
238 nsegstart * sizeof (unsigned));
239 gerror (err);
240 }
241 segstartpos = 0;
242 for (j = 0; j < p.nfreq; j++)
243 {
244 p1 = &(p.fplan[j]);
245 p1->segstart = &(segstartmemory[segstartpos]);
246 p1->segstart[0] = 0;
247 if (p1->nseg > 1)
248 {
249 segincr =
250 (double) (ndata - p1->dftlen) / (double) (p1->nseg - 1);
251 for (k = 1; k < p1->nseg - 1; k++)
252 p1->segstart[k] = myround ((double) k * segincr);
253 p1->segstart[p1->nseg - 1] = ndata - p1->dftlen;
254 }
255 segstartpos += p1->nseg;
256 }
257 }
258 return p;
259 }
260
261 void
262 ltf_plan_free (ltf_plan p)
263 {
264 if ((p.fplan[0]).segstart != NULL)
265 free ((p.fplan[0]).segstart);
266 free (p.fplan);
267 }
268
269 void
270 fprint (double f, char *s)
271 {
272 if (f < 1e-5)
273 sprintf (s, "%.3f$\\mu$", 1e6 * f);
274 else if (f < 1e-4)
275 sprintf (s, "%.2f$\\mu$", 1e6 * f);
276 else if (f < 1e-3)
277 sprintf (s, "%.1f$\\mu$", 1e6 * f);
278 else if (f < 1e-2)
279 sprintf (s, "%.3fm", 1e3 * f);
280 else if (f < 1e-1)
281 sprintf (s, "%.2fm", 1e3 * f);
282 else if (f < 1)
283 sprintf (s, "%.1fm", 1e3 * f);
284 else
285 sprintf (s, "%.3f", f);
286 }
287
288 int
289 main (void)
290 {
291 ltf_plan p;
292 ltf_plan_one *p1;
293 unsigned ndata = 1000000;
294 double fsamp = 10.;
295 double ovlap = 75;
296 double binmin = 5.3;
297 unsigned mindftlen = 100;
298 unsigned freqdes = 200;
299 unsigned avgdes = 100;
300 unsigned j, k;
301 double eq1, eq2;
302 double dfdown, dfup;
303 double logfact, logres;
304
305 logfact = (pow (ndata / 2., 1. / freqdes) - 1.);
306
307 p = plan (ndata, fsamp, ovlap, binmin, mindftlen, freqdes, avgdes, 1);
308
309 if (TEX)
310 {
311
312 printf ("\\section{Sample output}\n");
313 printf
314 ("As reference for other implementations, here are the results for the case\\\\\n");
315 printf ("$N_{\\rm data}$ ({\\tt ndata}) $=%d$\\\\\n", ndata);
316 printf ("$f_{\\rm samp}$ ({\\tt fsamp}) $=%g$\\,Hz\\\\\n", fsamp);
317 printf ("$\\xi_{\\rm ovlap}$ ({\\tt ovlap}) $=%g$\\,\\%%\\\\\n", ovlap);
318 printf ("$b_{\\rm min}$ ({\\tt binmin}) $=%g$\\\\\n", binmin);
319 printf ("$L_{\\rm min}$ ({\\tt mindftlen}) $=%d$\\\\\n", mindftlen);
320 printf ("$J_{\\rm des}$ ({\\tt freqdes}) $=%d$\\\\\n", freqdes);
321 printf ("$K_{\\rm des}$ ({\\tt avgdes}) $=%d$\n", avgdes);
322 printf ("\n");
323 printf
324 ("Usually, $J_{\\rm des}$ ({\\tt freqdes}) will be chosen higher (1000\
325 is a typical value); %d has been chosen here to save space in the\
326 printed table.\n",
327 freqdes);
328 printf ("\n");
329 printf
330 ("Targets that are not met are printed {\\bfseries \\slshape like this}\n");
331 printf ("\n");
332
333 printf ("\\small{\n");
334 printf
335 ("\\tablehead{$j$ & $f_j$ & $r_j$ & $b_j$ & $K_j$ & $L_j$ & $\\frac{f_j-f_{j-1}}{r_j}$ & $\\frac{f_{j+1}-f_j}{r_j}$ & $\\frac{r_j}{c\\cdot f_j}$ & $q_k^{(j)}$\\\\\\hline}\n");
336 printf ("\\begin{supertabular}{|r|r|r|r|r|r|r|r|r|l|}\n");
337 }
338
339 for (j = 0; j < p.nfreq; j++)
340 {
341 p1 = &(p.fplan[j]);
342
343 /* check required relations */
344 eq1 = p1->f - p1->fres * p1->bin;
345 assert (fabs (eq1 / p1->f) < 1e-10);
346 eq2 = p.fsamp - p1->fres * p1->dftlen;
347 assert (fabs (eq2 / p.fsamp) < 1e-10);
348
349 if (j > 0)
350 dfdown = p.fplan[j].f - p.fplan[j - 1].f;
351 else
352 dfdown = 0;
353 if (j < p.nfreq - 1)
354 dfup = p.fplan[j + 1].f - p.fplan[j].f;
355 else
356 dfup = 0;
357 logres = p1->fres / (p1->f * logfact);
358
359 if (TEX)
360 {
361 char sf[80], sfres[80], snseg[80], sdown[80], sup[80], slogres[80];
362 fprint (p1->f, sf);
363 fprint (p1->fres, sfres);
364 if (p1->nseg < avgdes)
365 sprintf (snseg, "{\\bfseries \\slshape %7d}", p1->nseg);
366 else
367 sprintf (snseg, "%7d", p1->nseg);
368 if (j > 0)
369 sprintf (sdown, "%.3f", dfdown / p1->fres);
370 else
371 sprintf (sdown, "---");
372 if (j < p.nfreq - 1)
373 sprintf (sup, "%.3f", dfup / p1->fres);
374 else
375 sprintf (sup, "---");
376 if (logres < .995 || logres > 1.005)
377 sprintf (slogres, "{\\bfseries \\slshape %.3f}", logres);
378 else
379 sprintf (slogres, "%.3f", logres);
380 printf
381 ("%4d & %s & %s & %.2f & %s & %7d & %s & %s & %s & ",
382 j, sf, sfres, p1->bin, snseg, p1->dftlen, sdown, sup, slogres);
383 }
384 else
385 {
386 printf ("%4d %20.20f %20.20f %20.20f %20d %20d %20.20f %20.20f %20.20f ", j,
387 p1->f, p1->fres, p1->bin, p1->nseg, p1->dftlen,
388 dfdown / p1->fres, dfup / p1->fres, logres);
389 }
390 if (p1->segstart != NULL)
391 {
392 // if (p1->nseg < 5)
393 // {
394 // for (k = 0; k < p1->nseg; k++)
395 // printf ("%u ", p1->segstart[k]);
396 // printf ("\\\\\n");
397 // }
398 // else
399 // {
400 // printf ("%u %u %u ... %u\\\\\n",
401 // p1->segstart[0],
402 // p1->segstart[1], p1->segstart[2],
403 // p1->segstart[p1->nseg - 1]);
404 // }
405 printf("\n");
406 assert (p1->segstart[p1->nseg - 1] + p1->dftlen == ndata);
407 }
408 else
409 printf (" (NULL)\n");
410 }
411 if (TEX)
412 {
413 printf ("\\end{supertabular}}\n");
414 }
415 // else
416 // printf ("% max. %u segments %u dftlen\n", p.maxnseg, p.maxdftlen);
417 ltf_plan_free (p);
418 return 0;
419 }