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 #include <fftw3.h>
00027 #include "astro.h"
00028
00029
00030 #define absval(x) (((x) < 0) ? (-(x)) : (x))
00031 #define minval(x,y) (((x) < (y)) ? (x) : (y))
00032 #define maxval(x,y) (((x) < (y)) ? (y) : (x))
00033 #define very_small (1.0e-30)
00034 #define is_very_small(x) (absval(x) < very_small)
00035 #define is_even(x) (!((x)%2))
00036 #define is_odd(x) ((x)%2)
00037
00038
00039
00040
00041
00042
00043
00044 void helio2mlat(float *map, float *map_mlat, int map_cols, int map_rows, int lmax, int map_lmax)
00045 {
00046 int i, row, col;
00047 int map_cols2 = map_cols / 2;
00048 int nout = (lmax + 1) * 2;
00049 int lfft, nfft, nok;
00050 double norm = 1.0, normx;
00051 float *buf, *wbuf, *bp;
00052 float *ip, *inp = map;
00053 float *op, *outp = map_mlat;
00054 fftwf_plan fftwp;
00055
00056 lfft = 2 * map_lmax;
00057 nfft = lfft + 2;
00058
00059
00060 buf = (float *)(malloc(nfft * sizeof(float)));
00061 wbuf = (float *)(malloc(nfft * sizeof(float)));
00062 fftwp = fftwf_plan_r2r_1d(lfft, buf, wbuf, FFTW_R2HC, FFTW_ESTIMATE);
00063
00064
00065 for (row = 0; row < map_rows; row++) {
00066
00067
00068 bp = buf;
00069 ip = inp + map_cols * row + map_cols2;
00070 for (col = 0; col <= map_cols2; col++) {
00071 if (!isnan(*ip)) {
00072 *bp++ = *ip;
00073 } else
00074 *bp++ = 0.0;
00075 ip++;
00076 }
00077
00078 bp = buf + lfft - map_cols2;
00079 ip = inp + map_cols * row;
00080 for (col = 0; col < map_cols2; col++) {
00081 if (!isnan(*ip)) {
00082 *bp++ = *ip;
00083 } else
00084 *bp++ = 0.0;
00085 ip++;
00086 }
00087
00088
00089 norm = 1. / lfft;
00090
00091
00092 fftwf_execute(fftwp);
00093
00094
00095
00096 for (int i = 0; i < nout / 2; i++) {
00097 op = outp + 2 * i * map_rows + row;
00098 *op = wbuf[i] * norm;
00099 }
00100
00101 *(outp + map_rows + row) = 0.0;
00102
00103 normx = -norm;
00104 for (int i = 0; i < nout / 2; i++) {
00105 op = outp + (2 * i + 1) * map_rows + row;
00106 *op = wbuf[lfft - i] * normx;
00107 }
00108 }
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 void scopy_(int *n, float *x, const int *incx, float *y, const int *incy);
00120 extern int setplm_(int *lmin, int *lmax, int *m, int *nx, int *indx,
00121 double *x, int *nplm, double *plm);
00122 void sgemm_(const char *transa, const char *transb,
00123 int *l, int *n, int *m, float *alpha,
00124 const float *a, int *lda, float *b, int *ldb,
00125 float *beta, void *c, int *ldc, int na, int nb);
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 void qdotprod(float *map_mlat, float *out_coeff, int map_rows, int lmin, int lmax, float sinBdelta)
00136 {
00137 int i, l, m, modd, meven;
00138
00139 float *oddpart, *evenpart, *inptr, *workptr, *mptr, *outptr;
00140 float *folded, *masks, *real4evenl, *real4oddl, *imag4evenl, *imag4oddl, *outx;
00141
00142 double *plm, *saveplm, *latgrid;
00143 int *indx;
00144 double *plmptr;
00145 float *maskptr;
00146
00147 int nrecs = 1;
00148 int lmax1 = lmax + 1;
00149 int mx, msize = lmax1, foldedsize;
00150 int imagesize = map_rows * 2 * msize;
00151
00152
00153 int increment1 = 1, increment2 = 2;
00154
00155
00156 char transpose[] = "t";
00157 char normal[] = "n";
00158 float one = 1.0;
00159 float zero = 0.0;
00160 float cnorm;
00161
00162 int lfirst, llast, ifirst, ilast, lstart, ldone;
00163 int lfirsteven, llasteven, nevenl, lfirstodd, llastodd, noddl;
00164 int fromoffset, tooffset, imageoffset;
00165
00166 int nlat = map_rows / 2, latx, ilatx, poslatx, neglatx, moffset;
00167
00168 int nlatx = 2 * (nlat / 2) + 1;
00169
00170 #ifdef __linux__
00171 if (nlat % 4) nlatx = 4 * (nlat / 4 + 1);
00172 else nlatx = nlat;
00173 #endif
00174
00175 int snx;
00176 int maxnsn = nrecs;
00177 int nsn = maxnsn, fournsn = 4 * nsn;
00178 int lchunksize = msize;
00179
00180 real4evenl = (float *)(malloc(nlatx * maxnsn * sizeof(float)));
00181 real4oddl = (float *)(malloc(nlatx * maxnsn * sizeof(float)));
00182 imag4evenl = (float *)(malloc(nlatx * maxnsn * sizeof(float)));
00183 imag4oddl = (float *)(malloc(nlatx * maxnsn * sizeof(float)));
00184 outx = (float *)(malloc(maxnsn * 2 * lchunksize * sizeof(float)));
00185
00186 plm = (double *)(malloc(lmax1 * nlat * sizeof(double)));
00187 saveplm = (double *)(malloc(lmax1 * nlat * 2 * sizeof(double)));
00188 latgrid = (double *)(malloc(nlat * sizeof(double)));
00189 for (i = 0; i < nlat; i++) latgrid[i] = (i + 0.5) * sinBdelta;
00190
00191 indx = (int *)(malloc(lmax1 * sizeof(int)));
00192 for (l = 0; l <= lmax; l++) indx[l] = l;
00193
00194 masks = (float *)(malloc(nlat * lchunksize * sizeof(float)));
00195
00196 foldedsize = 4 * nlat * lmax1 * maxnsn;
00197 folded = (float *)(malloc(foldedsize * sizeof(float)));
00198
00199 oddpart = (float *)(malloc(nlat * sizeof(float)));
00200 evenpart = (float *)(malloc(nlat * sizeof(float)));
00201
00202 inptr = map_mlat;
00203 imageoffset = 0;
00204
00205 for (mx = 0; mx < 2 * msize; mx++) {
00206 moffset = mx * map_rows;
00207 mptr = inptr + moffset;
00208 for (latx = 0; latx < nlat; latx++) {
00209 poslatx = nlat + latx; neglatx = nlat - 1 - latx;
00210 evenpart[latx] = mptr[poslatx] + mptr[neglatx];
00211 oddpart[latx] = mptr[poslatx] - mptr[neglatx];
00212 }
00213 workptr = folded + imageoffset + moffset;
00214 scopy_ (&nlat, evenpart, &increment1, workptr, &increment1);
00215 workptr += nlat;
00216 scopy_ (&nlat, oddpart, &increment1, workptr, &increment1);
00217 }
00218
00219
00220
00221
00222 ldone = -1;
00223
00224
00225
00226
00227
00228
00229
00230 cnorm = sqrt(2.) * sinBdelta;
00231
00232 lfirst = 0;
00233 llast = lmax;
00234
00235
00236 ifirst = lfirst * (lfirst + 1) / 2;
00237 ilast = (llast + 1) * (llast + 2) / 2 - 1;
00238
00239 outptr = out_coeff;
00240
00241
00242 for (m = 0; m <= llast; m++) {
00243 modd = is_odd(m);
00244 meven = !modd;
00245 lstart = maxval(lfirst, m);
00246
00247
00248 if ((lstart - 1) == ldone) {
00249
00250 if ((lstart - 2) >= m)
00251 for (latx = 0; latx < nlat; latx++)
00252 plm[(lstart - 2) * nlat + latx] = saveplm[m * nlat + latx];
00253 if ((lstart - 1) >= m)
00254 for (latx = 0; latx < nlat; latx++)
00255 plm[(lstart - 1) * nlat + latx] = saveplm[msize * nlat + m * nlat + latx];
00256
00257 setplm_ (&lstart, &llast, &m, &nlat, indx, latgrid, &nlat, plm);
00258 } else {
00259
00260 setplm_ (&m, &llast, &m, &nlat, indx, latgrid, &nlat, plm);
00261 }
00262
00263
00264 if ((llast-1) >= m)
00265 for (latx = 0; latx < nlat; latx++)
00266 saveplm[m * nlat + latx] = plm[(llast - 1) * nlat + latx];
00267 for (latx = 0; latx < nlat; latx++)
00268 saveplm[msize * nlat + m * nlat + latx] = plm[llast * nlat + latx];
00269 ldone = llast;
00270
00271
00272
00273
00274
00275 plmptr = plm + nlat * lstart;
00276 maskptr = masks;
00277 latx = nlat * (llast - lstart + 1);
00278 for (ilatx = 0; ilatx < latx; ilatx++)
00279 maskptr[ilatx] = plmptr[ilatx];
00280
00281 snx = 0;
00282
00283
00284
00285
00286 scopy_ (&nlat,
00287 folded + nlat * (4 * m + modd) + snx * imagesize,
00288 &increment1,
00289 real4evenl + snx * nlatx,
00290 &increment1);
00291 scopy_ (&nlat,
00292 folded + nlat * (4 * m + meven) + snx * imagesize,
00293 &increment1,
00294 real4oddl + snx * nlatx,
00295 &increment1);
00296 scopy_ (&nlat,
00297 folded + nlat * (4 * m + 2 + modd) + snx * imagesize,
00298 &increment1,
00299 imag4evenl + snx * nlatx,
00300 &increment1);
00301 scopy_ (&nlat,
00302 folded + nlat * (4 * m + 2 + meven) + snx * imagesize,
00303 &increment1,
00304 imag4oddl + snx * nlatx,
00305 &increment1);
00306
00307
00308 lfirsteven = is_even(lstart) ? lstart : lstart + 1;
00309 llasteven = is_even(llast) ? llast : llast - 1;
00310 nevenl = (llasteven - lfirsteven) / 2 + 1;
00311
00312
00313 sgemm_ (transpose,
00314 normal,
00315 &nsn,
00316 &nevenl,
00317 &nlat,
00318 &cnorm,
00319 real4evenl,
00320 &nlatx,
00321 masks + nlat * (lfirsteven - lstart),
00322 &map_rows,
00323 &zero,
00324 outx + nsn * 2 * (lfirsteven - lstart),
00325 &fournsn,
00326 1,
00327 1);
00328
00329 sgemm_ (transpose,
00330 normal,
00331 &nsn,
00332 &nevenl,
00333 &nlat,
00334 &cnorm,
00335 imag4evenl,
00336 &nlatx,
00337 masks + nlat * (lfirsteven - lstart),
00338 &map_rows,
00339 &zero,
00340 outx + nsn * ( 2 * (lfirsteven - lstart) + 1),
00341 &fournsn,
00342 1,
00343 1);
00344
00345
00346 lfirstodd = is_odd(lstart) ? lstart : lstart + 1;
00347 llastodd = is_odd(llast) ? llast : llast - 1;
00348 noddl = (llastodd - lfirstodd) / 2 + 1;
00349
00350 sgemm_ (transpose,
00351 normal,
00352 &nsn,
00353 &noddl,
00354 &nlat,
00355 &cnorm,
00356 real4oddl,
00357 &nlatx,
00358 masks + nlat * (lfirstodd - lstart),
00359 &map_rows,
00360 &zero,
00361 outx + nsn * 2 * (lfirstodd - lstart),
00362 &fournsn,
00363 1,
00364 1);
00365
00366 sgemm_ (transpose,
00367 normal,
00368 &nsn,
00369 &noddl,
00370 &nlat,
00371 &cnorm,
00372 imag4oddl,
00373 &nlatx,
00374 masks + nlat * (lfirstodd - lstart),
00375 &map_rows,
00376 &zero,
00377 outx + nsn * (2 * (lfirstodd - lstart) + 1),
00378 &fournsn,
00379 1,
00380 1);
00381
00382
00383
00384 for (l = lstart; l <= llast; l++) {
00385 fromoffset = 2 * nsn * (l - lstart);
00386 tooffset = 2 * nsn * (l * (l + 1) / 2 + m - ifirst);
00387 scopy_ (&nsn,
00388 outx + fromoffset,
00389 &increment1,
00390 outptr + tooffset,
00391 &increment2);
00392 scopy_ (&nsn,
00393 outx + fromoffset + nsn,
00394 &increment1,
00395 outptr + tooffset + 1,
00396 &increment2);
00397 }
00398
00399 }
00400 }