Healpix C++  3.83
hpxtest.cc
1 /*
2  * This file is part of Healpix_cxx.
3  *
4  * Healpix_cxx is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * Healpix_cxx is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with Healpix_cxx; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  * For more information about HEALPix, see http://healpix.sourceforge.net
19  */
20 
21 /*
22  * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik
23  * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
24  * (DLR).
25  */
26 
27 /*
28  * Copyright (C) 2004-2017 Max-Planck-Society
29  * Author: Martin Reinecke
30  */
31 
32 /*
33 
34 Candidates for testing the validity of the Healpix routines:
35 
36 - done: ang2pix(pix2ang(i)) = i for all Healpix_Bases
37 - done: pix2ang(ang2pix(ptg)) dot ptg > 1-delta for all Healpix_Bases
38 - done: ring2nest(nest2ring(i)) = i for all hierarchical Healpix_Bases
39 - done: downgrade(upgrade(map)) = map for all maps
40 - done: map and downgraded map should have same average
41 - done: alm2map(map2alm(map)) approx map (same for pol)
42 - partly done: neighbor tests
43 - powspec -> alm -> powspec (should produce similar powspecs, also for pol)
44 - done: two swap_schemes() should produce original map
45 - done: query_disc tests (dot products etc.)
46 - a_lms: test Set(), Scale(), Add(), alm(l,m) = alm.mstart(m)[l], etc.
47 
48 */
49 
50 #include <iostream>
51 #include "healpix_base.h"
52 #include "healpix_map.h"
53 #include "arr.h"
54 #include "planck_rng.h"
55 #include "lsconstants.h"
56 #include "alm.h"
57 #include "alm_healpix_tools.h"
58 #include "alm_powspec_tools.h"
59 #include "geom_utils.h"
60 #include "walltimer.h"
61 #include "announce.h"
62 #include "compress_utils.h"
63 #include "moc.h"
64 #include "moc_fitsio.h"
65 #include "crangeset.h"
66 #include "weight_utils.h"
67 #include "powspec.h"
68 
69 using namespace std;
70 
71 #define UNITTESTS
72 
73 #ifdef UNITTESTS
74 int errcount=0;
75 #define FAIL(a) {a; if (++errcount>100) planck_fail("unit test errors");}
76 #else
77 #define FAIL(a) a;
78 #endif
79 
80 const int nsamples = 1000000;
81 
82 planck_rng rng;
83 
84 namespace {
85 
86 void random_dir (pointing &ptg)
87  {
88  ptg.theta = acos(rng.rand_uni()*2-1);
89  ptg.phi = rng.rand_uni()*twopi;
90  }
91 void random_zphi (double &z, double &phi)
92  {
93  z = rng.rand_uni()*2-1;
94  phi = rng.rand_uni()*twopi;
95  }
96 
97 template<typename I> string bname()
98  { return string("(basetype: ")+type2typename<I>()+")"; }
99 
100 
101 template<typename I> rangeset<I> randomRangeSet(int num, I start, int dist)
102  {
103  rangeset<I> rs;
104  I curval=start;
105  for (int i=0; i<num; ++i)
106  {
107  I v1=curval+1+(rng.int_rand_uni()%dist);
108  I v2=v1+1+(rng.int_rand_uni()%dist);
109  rs.append(v1,v2);
110  curval=v2;
111  }
112  return rs;
113  }
114 template<typename I> Moc<I> randomMoc(int num, I start, int dist)
115  {
116  Moc<I> moc;
117  I curval=start+(I(1)<<(2*Moc<I>::maxorder));
118  for (int i=0; i<num; ++i)
119  {
120  I v1=curval+1+(rng.int_rand_uni()%dist);
121  I v2=v1+1+(rng.int_rand_uni()%dist);
122  moc.addPixelRange(Moc<I>::maxorder,v1,v2);
123  curval=v2;
124  }
125  return moc;
126  }
127 
128 template<typename I> rangeset<I> makeRS(const string &input)
129  {
130  istringstream is(input);
131  rangeset<I> res;
132  I a,b;
133  while (is)
134  {
135  is>>a>>b;
136  planck_assert (is||is.eof(),"aargh");
137  if (is) res.append(a,b);
138  }
139  return res;
140  }
141 template<typename I> void rsOps(const rangeset<I> &a, const rangeset<I> &b)
142  {
143  planck_assert(!b.overlaps(a.op_andnot(b)),"error");
144  planck_assert(a.op_or(b).nval()>=a.nval(),"error");
145  planck_assert(a.op_or(b).nval()>=b.nval(),"error");
146  planck_assert(a.op_and(b).nval()<=a.nval(),"error");
147  planck_assert(a.op_and(b).nval()<=b.nval(),"error");
148  planck_assert(a.op_or(b).contains(a),"error");
149  planck_assert(a.op_or(b).contains(b),"error");
150  planck_assert(!a.op_andnot(b).overlaps(b),"error");
151  planck_assert(!b.op_andnot(a).overlaps(a),"error");
152  planck_assert(a.op_or(b).nval()==a.nval()+b.nval()-a.op_and(b).nval(),
153  "error");
154  planck_assert(a.op_or(b).op_andnot(a.op_and(b)).nval()==
155  a.op_or(b).nval()-a.op_and(b).nval(),"error");
156  planck_assert(a.op_xor(b)==a.op_andnot(b).op_or(b.op_andnot(a)),"error");
157  }
158 template<typename I> void check_rangeset()
159  {
160  cout << "testing rangeset " << bname<I>() << endl;
161  {
162  rangeset<I> b;
163  b.append(1,11);
164  planck_assert(b==makeRS<I>("1 11"),"mismatch");
165  b.append(10,15);
166  planck_assert(b==makeRS<I>("1 15"),"mismatch");
167  b.append(1,15);
168  planck_assert(b==makeRS<I>("1 15"),"mismatch");
169  b.append(7,15);
170  planck_assert(b==makeRS<I>("1 15"),"mismatch");
171  b.append(30,41);
172 #if 0
173  planck_assert(b==makeRS<I>("1 15 30 41"),"mismatch");
174  try
175  {
176  b.append(29,31);
177  planck_fail("Should have raised an IllegalArgumentException");
178  }
179  catch (PlanckError E) {}
180 #endif
181  }
182  {
183  rangeset<I> b=makeRS<I>("1 11 30 41");
184  planck_assert(!b.contains(0),"error");
185  planck_assert(b.contains(1),"error");
186  planck_assert(b.contains(5),"error");
187  planck_assert(b.contains(10),"error");
188  planck_assert(!b.contains(11),"error");
189  planck_assert(!b.contains(29),"error");
190  planck_assert(b.contains(30),"error");
191  planck_assert(b.contains(35),"error");
192  planck_assert(b.contains(40),"error");
193  planck_assert(!b.contains(41),"errror");
194  }
195  {
196  rangeset<I> b;
197  b.add(5, 11);
198  planck_assert(b==makeRS<I>("5 11"),"error");
199  b.add(1, 7);
200  planck_assert(b==makeRS<I>("1 11"),"error");
201  b.add(1, 11);
202  planck_assert(b==makeRS<I>("1 11"),"error");
203  b.add(30, 41);
204  planck_assert(b==makeRS<I>("1 11 30 41"),"error");
205  b.add(1, 11);
206  planck_assert(b==makeRS<I>("1 11 30 41"),"error");
207  b.add(-1,0);
208  planck_assert(b==makeRS<I>("-1 0 1 11 30 41"),"error");
209  b.add(-2,-1);
210  planck_assert(b==makeRS<I>("-2 0 1 11 30 41"),"error");
211  b.add(-2,-1);
212  planck_assert(b==makeRS<I>("-2 0 1 11 30 41"),"error");
213  b.add(2, 11);
214  planck_assert(b==makeRS<I>("-2 0 1 11 30 41"),"error");
215  b.add(1, 10);
216  planck_assert(b==makeRS<I>("-2 0 1 11 30 41"),"error");
217  b.add(15, 21);
218  planck_assert(b==makeRS<I>("-2 0 1 11 15 21 30 41"),"error");
219  }
220  {
221  rangeset<I> b = makeRS<I>("0 11 20 31");
222  b.remove(5,25);
223  planck_assert(b==makeRS<I>("0 5 25 31"),"error");
224  b.remove(31,32);
225  planck_assert(b==makeRS<I>("0 5 25 31"),"error");
226  b.remove(35,38);
227  planck_assert(b==makeRS<I>("0 5 25 31"),"error");
228  b.remove(-90,-80);
229  planck_assert(b==makeRS<I>("0 5 25 31"),"error");
230  b.remove(27,29);
231  planck_assert(b==makeRS<I>("0 5 25 27 29 31"),"error");
232  b.remove(25,26);
233  planck_assert(b==makeRS<I>("0 5 26 27 29 31"),"error");
234  b.remove(4,6);
235  planck_assert(b==makeRS<I>("0 4 26 27 29 31"),"error");
236  b.remove(-20,40);
237  planck_assert(b==makeRS<I>(""),"error");
238  b.remove(-20,40);
239  planck_assert(b==makeRS<I>(""),"error");
240  }
241  {
242  rangeset<I> b = makeRS<I>("0 11 20 31");
243  b.intersect(2,29);
244  planck_assert(b==makeRS<I>("2 11 20 29"),"error");
245  b.intersect(-8,50);
246  planck_assert(b==makeRS<I>("2 11 20 29"),"error");
247  b.intersect(2,50);
248  planck_assert(b==makeRS<I>("2 11 20 29"),"error");
249  b.intersect(2,29);
250  planck_assert(b==makeRS<I>("2 11 20 29"),"error");
251  b.intersect(-18,29);
252  planck_assert(b==makeRS<I>("2 11 20 29"),"error");
253  b.intersect(3,11);
254  planck_assert(b==makeRS<I>("3 11"),"error");
255  b = makeRS<I>("0 11 20 31");
256  b.intersect(3,15);
257  planck_assert(b==makeRS<I>("3 11"),"error");
258  b = makeRS<I>("0 11 20 31");
259  b.intersect(17,30);
260  planck_assert(b==makeRS<I>("20 30"),"error");
261  b = makeRS<I>("0 11 20 31");
262  b.intersect(11,20);
263  planck_assert(b==makeRS<I>(""),"error");
264  b = makeRS<I>("0 11 20 31");
265  b.intersect(-8,-7);
266  planck_assert(b==makeRS<I>(""),"error");
267  b = makeRS<I>("0 11 20 31");
268  b.intersect(31,35);
269  planck_assert(b==makeRS<I>(""),"error");
270  }
271  {
272  planck_assert(makeRS<I>("1 11 20 31 40 56")==
273  makeRS<I>("20 31 40 51").op_or
274  (makeRS<I>("1 11 45 56")),"error");
275  planck_assert(makeRS<I>("1 11 45 56")==
276  makeRS<I>("").op_or
277  (makeRS<I>("1 11 45 56")),"error");
278  planck_assert(makeRS<I>("1 11 45 56")==
279  makeRS<I>("1 11 45 56").op_or
280  (makeRS<I>("")),"error");
281  }
282  {
283  planck_assert(makeRS<I>("22 24 45 51")==
284  makeRS<I>("20 31 40 51").op_and
285  (makeRS<I>("1 11 22 24 45 56")),"error");
286  planck_assert(makeRS<I>("20 31 40 51 90 101 110 121 200 201")==
287  makeRS<I>("10 101 110 121 200 221").op_and
288  (makeRS<I>("20 31 40 51 90 201")),"error");
289  planck_assert(makeRS<I>("")==
290  makeRS<I>("20 31 40 51").op_and
291  (makeRS<I>("")),"error");
292  planck_assert(makeRS<I>("")==
293  makeRS<I>("").op_and
294  (makeRS<I>("20 31 40 51")),"error");
295  }
296  {
297  planck_assert(makeRS<I>("20 31 40 45")==
298  makeRS<I>("20 31 40 51").op_andnot
299  (makeRS<I>("1 11 45 56")),"error");
300  planck_assert(makeRS<I>("")==
301  makeRS<I>("").op_andnot
302  (makeRS<I>("1 11 45 56")),"error");
303  planck_assert(makeRS<I>("1 11 45 56")==
304  makeRS<I>("1 11 45 56").op_andnot
305  (makeRS<I>("")),"error");
306  }
307  {
308  rangeset<I> b = makeRS<I>("20 31 40 51");
309 
310  planck_assert(!b.contains(0,11),"error");
311  planck_assert(!b.contains(10,21),"error");
312  planck_assert(!b.contains(19,20),"error");
313  planck_assert(b.contains(20,21),"error");
314  planck_assert(b.contains(21,22),"error");
315  planck_assert(b.contains(20,31),"error");
316  planck_assert(!b.contains(25,36),"error");
317  planck_assert(b.contains(30,31),"error");
318  planck_assert(!b.contains(31,32),"error");
319  planck_assert(!b.contains(35,38),"error");
320  planck_assert(!b.contains(35,46),"error");
321  planck_assert(b.contains(40,41),"error");
322  planck_assert(!b.contains(45,56),"error");
323  planck_assert(!b.contains(60,71),"error");
324  }
325  {
326  rangeset<I> b = makeRS<I>("20 31 40 51");
327 
328  planck_assert(b.contains(makeRS<I>("20 31 40 51")),"error");
329  planck_assert(b.contains(makeRS<I>("20 21")),"error");
330  planck_assert(b.contains(makeRS<I>("50 51")),"error");
331  planck_assert(!b.contains(makeRS<I>("19 31 40 51")),"error");
332  planck_assert(!b.contains(makeRS<I>("20 31 40 52")),"error");
333  planck_assert(!b.contains(makeRS<I>("20 51")),"error");
334  planck_assert(!b.contains(makeRS<I>("0 1")),"error");
335  planck_assert(!b.contains(makeRS<I>("0 20 31 40 51 100")),"error");
336  }
337  {
338  rangeset<I> b = makeRS<I>("20 31 40 51");
339 
340  planck_assert(!b.overlaps(0,11),"error");
341  planck_assert(b.overlaps(10,21),"error");
342  planck_assert(!b.overlaps(19,20),"error");
343  planck_assert(b.overlaps(20,21),"error");
344  planck_assert(b.overlaps(21,22),"error");
345  planck_assert(b.overlaps(20,31),"error");
346  planck_assert(b.overlaps(25,36),"error");
347  planck_assert(b.overlaps(30,37),"error");
348  planck_assert(!b.overlaps(31,32),"error");
349  planck_assert(!b.overlaps(35,38),"error");
350  planck_assert(b.overlaps(35,46),"error");
351  planck_assert(b.overlaps(40,41),"error");
352  planck_assert(b.overlaps(45,56),"error");
353  planck_assert(!b.overlaps(60,71),"error");
354  }
355  {
356  rangeset<I> b = makeRS<I>("20 31 40 51");
357 
358  planck_assert(b.overlaps(makeRS<I>("20 31 40 51")),"error");
359  planck_assert(b.overlaps(makeRS<I>("20 21")),"error");
360  planck_assert(b.overlaps(makeRS<I>("50 51")),"error");
361  planck_assert(b.overlaps(makeRS<I>("19 31 40 51")),"error");
362  planck_assert(b.overlaps(makeRS<I>("20 31 40 52")),"error");
363  planck_assert(b.overlaps(makeRS<I>("20 51")),"error");
364  planck_assert(!b.overlaps(makeRS<I>("0 1")),"error");
365  planck_assert(!b.overlaps(makeRS<I>("0 20 31 40 51 100")),"error");
366  }
367  {
368  const int niter = 1000;
369  for (int iter=0; iter<niter; ++iter)
370  {
371  rangeset<I> a = randomRangeSet<I>(1000, 0, 100);
372  rangeset<I> b = randomRangeSet<I>(1000, 0, 100);
373  rangeset<I> c = randomRangeSet<I>(10, 10000, 100);
374  rsOps(a,b);
375  rsOps(a,c);
376  rsOps(c,a);
377  }
378  }
379  }
380 template<typename I> crangeset<I> randomCRangeSet(int num, I start, int dist)
381  {
382  crangeset<I> rs;
383  I curval=start;
384  for (int i=0; i<num; ++i)
385  {
386  I v1=curval+1+(rng.int_rand_uni()%dist);
387  I v2=v1+1+(rng.int_rand_uni()%dist);
388  rs.append(v1,v2);
389  curval=v2;
390  }
391  return rs;
392  }
393 template<typename I> crangeset<I> makeCRS(const string &input)
394  {
395  istringstream is(input);
396  crangeset<I> res;
397  I a,b;
398  while (is)
399  {
400  is>>a>>b;
401  planck_assert (is||is.eof(),"aargh");
402  if (is) res.append(a,b);
403  }
404  return res;
405  }
406 template<typename I> void crsOps(const crangeset<I> &a, const crangeset<I> &b)
407  {
408  planck_assert(!b.overlaps(a.op_andnot(b)),"error");
409  planck_assert(a.op_or(b).nval()>=a.nval(),"error");
410  planck_assert(a.op_or(b).nval()>=b.nval(),"error");
411  planck_assert(a.op_and(b).nval()<=a.nval(),"error");
412  planck_assert(a.op_and(b).nval()<=b.nval(),"error");
413  planck_assert(a.op_or(b).contains(a),"error");
414  planck_assert(a.op_or(b).contains(b),"error");
415  planck_assert(!a.op_andnot(b).overlaps(b),"error");
416  planck_assert(!b.op_andnot(a).overlaps(a),"error");
417  planck_assert(a.op_or(b).nval()==a.nval()+b.nval()-a.op_and(b).nval(),
418  "error");
419  planck_assert(a.op_or(b).op_andnot(a.op_and(b)).nval()==
420  a.op_or(b).nval()-a.op_and(b).nval(),"error");
421  planck_assert(a.op_xor(b)==a.op_andnot(b).op_or(b.op_andnot(a)),"error");
422  }
423 template<typename I> void check_crangeset()
424  {
425  cout << "testing crangeset " << bname<I>() << endl;
426  {
427  crangeset<I> b;
428  b.append(1,11);
429  planck_assert(b==makeCRS<I>("1 11"),"mismatch");
430  b.append(10,15);
431  planck_assert(b==makeCRS<I>("1 15"),"mismatch");
432  b.append(1,15);
433  planck_assert(b==makeCRS<I>("1 15"),"mismatch");
434  b.append(7,15);
435  planck_assert(b==makeCRS<I>("1 15"),"mismatch");
436  b.append(30,41);
437 #if 0
438  planck_assert(b==makeRS<I>("1 15 30 41"),"mismatch");
439  try
440  {
441  b.append(29,31);
442  planck_fail("Should have raised an IllegalArgumentException");
443  }
444  catch (PlanckError E) {}
445 #endif
446  }
447  {
448  crangeset<I> b=makeCRS<I>("1 11 30 41");
449  planck_assert(!b.contains(0),"error");
450  planck_assert(b.contains(1),"error");
451  planck_assert(b.contains(5),"error");
452  planck_assert(b.contains(10),"error");
453  planck_assert(!b.contains(11),"error");
454  planck_assert(!b.contains(29),"error");
455  planck_assert(b.contains(30),"error");
456  planck_assert(b.contains(35),"error");
457  planck_assert(b.contains(40),"error");
458  planck_assert(!b.contains(41),"errror");
459  }
460  {
461  planck_assert(makeCRS<I>("1 11 20 31 40 56")==
462  makeCRS<I>("20 31 40 51").op_or
463  (makeCRS<I>("1 11 45 56")),"error");
464  planck_assert(makeCRS<I>("1 11 45 56")==
465  makeCRS<I>("").op_or
466  (makeCRS<I>("1 11 45 56")),"error");
467  planck_assert(makeCRS<I>("1 11 45 56")==
468  makeCRS<I>("1 11 45 56").op_or
469  (makeCRS<I>("")),"error");
470  }
471  {
472  planck_assert(makeCRS<I>("22 24 45 51")==
473  makeCRS<I>("20 31 40 51").op_and
474  (makeCRS<I>("1 11 22 24 45 56")),"error");
475  planck_assert(makeCRS<I>("20 31 40 51 90 101 110 121 200 201")==
476  makeCRS<I>("10 101 110 121 200 221").op_and
477  (makeCRS<I>("20 31 40 51 90 201")),"error");
478  planck_assert(makeCRS<I>("")==
479  makeCRS<I>("20 31 40 51").op_and
480  (makeCRS<I>("")),"error");
481  planck_assert(makeCRS<I>("")==
482  makeCRS<I>("").op_and
483  (makeCRS<I>("20 31 40 51")),"error");
484  }
485  {
486  planck_assert(makeCRS<I>("20 31 40 45")==
487  makeCRS<I>("20 31 40 51").op_andnot
488  (makeCRS<I>("1 11 45 56")),"error");
489  planck_assert(makeCRS<I>("")==
490  makeCRS<I>("").op_andnot
491  (makeCRS<I>("1 11 45 56")),"error");
492  planck_assert(makeCRS<I>("1 11 45 56")==
493  makeCRS<I>("1 11 45 56").op_andnot
494  (makeCRS<I>("")),"error");
495  }
496  {
497  crangeset<I> b = makeCRS<I>("20 31 40 51");
498 
499  planck_assert(!b.contains(0,11),"error");
500  planck_assert(!b.contains(10,21),"error");
501  planck_assert(!b.contains(19,20),"error");
502  planck_assert(b.contains(20,21),"error");
503  planck_assert(b.contains(21,22),"error");
504  planck_assert(b.contains(20,31),"error");
505  planck_assert(!b.contains(25,36),"error");
506  planck_assert(b.contains(30,31),"error");
507  planck_assert(!b.contains(31,32),"error");
508  planck_assert(!b.contains(35,38),"error");
509  planck_assert(!b.contains(35,46),"error");
510  planck_assert(b.contains(40,41),"error");
511  planck_assert(!b.contains(45,56),"error");
512  planck_assert(!b.contains(60,71),"error");
513  }
514  {
515  crangeset<I> b = makeCRS<I>("20 31 40 51");
516 
517  planck_assert(b.contains(makeCRS<I>("20 31 40 51")),"error");
518  planck_assert(b.contains(makeCRS<I>("20 21")),"error");
519  planck_assert(b.contains(makeCRS<I>("50 51")),"error");
520  planck_assert(!b.contains(makeCRS<I>("19 31 40 51")),"error");
521  planck_assert(!b.contains(makeCRS<I>("20 31 40 52")),"error");
522  planck_assert(!b.contains(makeCRS<I>("20 51")),"error");
523  planck_assert(!b.contains(makeCRS<I>("0 1")),"error");
524  planck_assert(!b.contains(makeCRS<I>("0 20 31 40 51 100")),"error");
525  }
526  {
527  crangeset<I> b = makeCRS<I>("20 31 40 51");
528 
529  planck_assert(!b.overlaps(0,11),"error");
530  planck_assert(b.overlaps(10,21),"error");
531  planck_assert(!b.overlaps(19,20),"error");
532  planck_assert(b.overlaps(20,21),"error");
533  planck_assert(b.overlaps(21,22),"error");
534  planck_assert(b.overlaps(20,31),"error");
535  planck_assert(b.overlaps(25,36),"error");
536  planck_assert(b.overlaps(30,37),"error");
537  planck_assert(!b.overlaps(31,32),"error");
538  planck_assert(!b.overlaps(35,38),"error");
539  planck_assert(b.overlaps(35,46),"error");
540  planck_assert(b.overlaps(40,41),"error");
541  planck_assert(b.overlaps(45,56),"error");
542  planck_assert(!b.overlaps(60,71),"error");
543  }
544  {
545  crangeset<I> b = makeCRS<I>("20 31 40 51");
546 
547  planck_assert(b.overlaps(makeCRS<I>("20 31 40 51")),"error");
548  planck_assert(b.overlaps(makeCRS<I>("20 21")),"error");
549  planck_assert(b.overlaps(makeCRS<I>("50 51")),"error");
550  planck_assert(b.overlaps(makeCRS<I>("19 31 40 51")),"error");
551  planck_assert(b.overlaps(makeCRS<I>("20 31 40 52")),"error");
552  planck_assert(b.overlaps(makeCRS<I>("20 51")),"error");
553  planck_assert(!b.overlaps(makeCRS<I>("0 1")),"error");
554  planck_assert(!b.overlaps(makeCRS<I>("0 20 31 40 51 100")),"error");
555  }
556  {
557  const int niter = 1000;
558  for (int iter=0; iter<niter; ++iter)
559  {
560  crangeset<I> a = randomCRangeSet<I>(1000, 0, 100);
561  crangeset<I> b = randomCRangeSet<I>(1000, 0, 100);
562  crangeset<I> c = randomCRangeSet<I>(10, 10000, 100);
563  crsOps(a,b);
564  crsOps(a,c);
565  crsOps(c,a);
566  }
567  }
568  }
569 template<typename I> void check_Moc()
570  {
571  cout << "testing MOC " << bname<I>() << endl;
572  Moc<I> moc;
573  moc.addPixelRange(0,4,5);
574  moc.addPixelRange(0,6,7);
575  moc.addPixelRange(2,4,17);
576  moc.addPixelRange(10,3000000,3000001);
577 
578  planck_assert(moc==moc.complement().complement(),"error");
579  planck_assert(moc==Moc<I>::fromUniq(moc.toUniq()),"error");
580  planck_assert(moc.maxOrder()==10,"error");
581  Moc<I> xtmp = moc.degradedToOrder(8,false);
582  planck_assert(moc.contains(xtmp),"error");
583  planck_assert(!xtmp.contains(moc),"error");
584  planck_assert(xtmp.overlaps(moc),"error");
585  xtmp=moc.degradedToOrder(8,true);
586  planck_assert(!moc.contains(xtmp),"error");
587  planck_assert(xtmp.contains(moc),"error");
588  planck_assert(xtmp.overlaps(moc),"error");
589  planck_assert(moc==Moc<I>::fromCompressed(moc.toCompressed()),"error");
590 #if 0
591  assertEquals("inconsistency",moc,MocUtil.mocFromString(" 0/4, 6 2/ \t 4 -16 10/3000000 \t\n "));
592  assertEquals("inconsistency",moc,MocUtil.mocFromString("0/6 2/ 5 2/4 2/6- 16 0/4 10/3000000"));
593  assertEquals("inconsistency",moc,MocUtil.mocFromString
594  ("{\"0\":[6] , \"2\": [5 ], \"2\":[ 4,6,7,8,9,10,11,12,13,14,15,16], \"0\":[4], \"10\":[3000000]}"));
595  assertEquals("inconsistency",moc,MocUtil.mocFromString(MocUtil.mocToStringASCII(moc)));
596  assertEquals("inconsistency",moc,MocUtil.mocFromString(MocUtil.mocToStringJSON(moc)));
597  ByteArrayOutputStream out= new ByteArrayOutputStream();
598  MocUtil.mocToFits(moc,out);
599  ByteArrayInputStream inp = new ByteArrayInputStream(out.toByteArray());
600  assertEquals("inconsistency",moc,MocUtil.mocFromFits(inp));
601 #endif
602  {
603  tsize niter = 100;
604  Moc<I> full; full.addPixelRange(0,0,12);
605  Moc<I> empty;
606  for (tsize iter=0; iter<niter; ++iter)
607  {
608  Moc<I> a = randomMoc<I>(1000, 0, 100);
609  planck_assert(a.complement().complement()==a,"error");
610  planck_assert(!a.overlaps(a.complement()),"error");
611  planck_assert(a.op_or(a.complement())==full,"error");
612  planck_assert(a.op_and(a.complement())==empty,"error");
613 #if 0
614  write_Moc_to_fits("!healpixtestmoctmp",a);
615  planck_assert(a==read_Moc_from_fits<I>("healpixtestmoctmp"),"FITS problem");
616 #endif
617  }
618  }
619  }
620 template<typename I> void check_compress()
621  {
622  cout << "testing interpolation coding " << bname<I>() << endl;
623  planck_assert(trailingZeros(4)==2,"error");
624  planck_assert(trailingZeros(5)==0,"error");
625  planck_assert(trailingZeros(int64(1)<<48)==48,"error");
626  for (tsize x=0; x<100; ++x)
627  {
628  rangeset<I> a = randomRangeSet<I>(1000, 0, 100);
629  rangeset<I> b;
630  for (tsize i=0; i<a.nranges(); ++i)
631  b.append(a.ivbegin(i)<<6,a.ivend(i)<<6);
632  const vector<I> &v=b.data();
633  obitstream obs;
634  interpol_encode(v.begin(),v.end(),obs);
635  vector<uint8> comp=obs.state();
636  vector<I> v2;
637  ibitstream ibs(comp);
638  interpol_decode(v2,ibs);
639  planck_assert(v==v2,"data mismatch");
640  }
641  }
642 
643 template<typename I> void check_ringnestring()
644  {
645  cout << "testing ring2nest(nest2ring(m))==m " << bname<I>() << endl;
646  for (int order=0; order<=T_Healpix_Base<I>::order_max; ++order)
647  {
648  T_Healpix_Base<I> base (order,RING);
649  for (int m=0; m<nsamples; ++m)
650  {
651  I pix = I(rng.rand_uni()*base.Npix());
652  if (base.ring2nest(base.nest2ring(pix))!=pix)
653  FAIL(cout<<" PROBLEM: order = "<<order<<", pixel = "<<pix<<endl)
654  }
655  }
656  }
657 
658 template<typename I> void check_nestpeanonest()
659  {
660  cout << "testing peano2nest(nest2peano(m))==m " << bname<I>() << endl;
661  for (int order=0; order<=T_Healpix_Base<I>::order_max; ++order)
662  {
663  T_Healpix_Base<I> base (order,NEST);
664  for (int m=0; m<nsamples; ++m)
665  {
666  I pix = I(rng.rand_uni()*base.Npix());
667  if (base.peano2nest(base.nest2peano(pix))!=pix)
668  FAIL(cout<<" PROBLEM: order = "<<order<<", pixel = "<<pix<<endl)
669  }
670  }
671  }
672 
673 template<typename I> void check_pixzphipix()
674  {
675  cout << "testing zphi2pix(pix2zphi(m))==m " << bname<I>() << endl;
677  for (int order=0; order<=omax; ++order)
678  {
679  T_Healpix_Base<I> base1 (order,RING), base2 (order,NEST);
680  for (int m=0; m<nsamples; ++m)
681  {
682  double z,phi;
683  I pix = I(rng.rand_uni()*base1.Npix());
684  base1.pix2zphi(pix,z,phi);
685  if (base1.zphi2pix(z,phi)!=pix)
686  FAIL(cout<<" PROBLEM: order = "<<order<<", pixel = "<<pix<<endl)
687  base2.pix2zphi(pix,z,phi);
688  if (base2.zphi2pix(z,phi)!=pix)
689  FAIL(cout<<" PROBLEM: order = "<<order<<", pixel = "<<pix<<endl)
690  }
691  }
692  for (I nside=3; nside<(I(1)<<omax); nside+=nside/2+1)
693  {
694  T_Healpix_Base<I> base (nside,RING,SET_NSIDE);
695  for (int m=0; m<nsamples; ++m)
696  {
697  double z,phi;
698  I pix = I(rng.rand_uni()*base.Npix());
699  base.pix2zphi(pix,z,phi);
700  if (base.zphi2pix(z,phi)!=pix)
701  FAIL(cout<<" PROBLEM: nside = "<<nside<<", pixel = "<<pix<<endl)
702  }
703  }
704  }
705 
706 template<typename I> void check_zphipixzphi()
707  {
708  cout << "testing pix2zphi(zphi2pix(ptg)) approx zphi " << bname<I>() << endl;
710  for (int order=0; order<=omax; ++order)
711  {
712  T_Healpix_Base<I> base1 (order,NEST), base2 (order,RING);
713  double mincos = min (cos(base1.max_pixrad()),0.999999999999999);
714  for (int m=0; m<nsamples; ++m)
715  {
716  double z,phi,z2,phi2;
717  random_zphi (z,phi);
718  base1.pix2zphi(base1.zphi2pix(z,phi),z2,phi2);
719  if (cosdist_zphi(z,phi,z2,phi2)<mincos)
720  FAIL(cout << " PROBLEM: order = " << order
721  << ", zphi = " << z << ", " << phi << endl)
722  base2.pix2zphi(base2.zphi2pix(z,phi),z2,phi2);
723  if (cosdist_zphi(z,phi,z2,phi2)<mincos)
724  FAIL(cout << " PROBLEM: order = " << order
725  << ", zphi = " << z << ", " << phi << endl)
726  }
727  }
728  for (int nside=3; nside<(I(1)<<omax); nside+=nside/2+1)
729  {
730  T_Healpix_Base<I> base (nside,RING,SET_NSIDE);
731  double mincos = min (cos(base.max_pixrad()),0.999999999999999);
732  for (int m=0; m<nsamples; ++m)
733  {
734  double z,phi,z2,phi2;
735  random_zphi (z,phi);
736  base.pix2zphi(base.zphi2pix(z,phi),z2,phi2);
737  if (cosdist_zphi(z,phi,z2,phi2)<mincos)
738  FAIL(cout << " PROBLEM: nside = " << nside
739  << ", zphi = " << z << ", " << phi << endl)
740  }
741  }
742  }
743 
744 template<typename I> void check_pixangpix()
745  {
746  cout << "testing ang2pix(pix2ang(m))==m " << bname<I>() << endl;
748  for (int order=0; order<=omax; ++order)
749  {
750  T_Healpix_Base<I> base1 (order,RING), base2 (order,NEST);
751  for (int m=0; m<nsamples; ++m)
752  {
753  I pix = I(rng.rand_uni()*base1.Npix());
754  if (base1.ang2pix(base1.pix2ang(pix))!=pix)
755  FAIL(cout<<" PROBLEM: order = "<<order<<", pixel = "<<pix<<endl)
756  if (base2.ang2pix(base2.pix2ang(pix))!=pix)
757  FAIL(cout<<" PROBLEM: order = "<<order<<", pixel = "<<pix<<endl)
758  }
759  }
760  for (I nside=3; nside<(I(1)<<omax); nside+=nside/2+1)
761  {
762  T_Healpix_Base<I> base (nside,RING,SET_NSIDE);
763  for (int m=0; m<nsamples; ++m)
764  {
765  I pix = I(rng.rand_uni()*base.Npix());
766  if (base.ang2pix(base.pix2ang(pix))!=pix)
767  FAIL(cout<<" PROBLEM: nside = "<<nside<<", pixel = "<<pix<<endl)
768  }
769  }
770  }
771 
772 template<typename I> void check_neighbors()
773  {
774  cout << "testing neighbor function " << bname<I>() << endl;
776  for (int order=0; order<=omax; ++order)
777  {
778  T_Healpix_Base<I> base (order,NEST), base2(order,RING);
779  double maxang = 2.01*base.max_pixrad();
780  for (int m=0; m<nsamples/10; ++m)
781  {
782  I pix = I(rng.rand_uni()*base.Npix());
783  fix_arr<I,8> nb,nb2;
784  vec3 pixpt = base.pix2vec(pix);
785  base.neighbors(pix,nb);
786  base2.neighbors(base.nest2ring(pix),nb2);
787  for (int n=0; n<8; ++n)
788  if (nb[n]<0)
789  planck_assert(nb2[n]<0,"neighbor inconsistency");
790  else
791  planck_assert(base.nest2ring(nb[n])==nb2[n],"neighbor inconsistency");
792  sort(&nb[0],&nb[0]+8);
793  int check=0;
794  for (int n=0; n<8; ++n)
795  {
796  if (nb[n]<0)
797  ++check;
798  else
799  {
800  if (v_angle(base.pix2vec(nb[n]),pixpt)>maxang)
801  FAIL(cout<<" PROBLEM: order = "<<order<<", pix = "<<pix<<endl)
802  if ((n>0) && (nb[n]==nb[n-1]))
803  FAIL(cout<<" PROBLEM: order = "<<order<<", pix = "<<pix<<endl)
804  }
805  }
806  planck_assert((check<=1)||((order==0)&&(check<=2)),"too few neighbors");
807  }
808  }
809  for (I nside=3; nside<(I(1)<<omax); nside+=nside/2+1)
810  {
811  T_Healpix_Base<I> base (nside,RING,SET_NSIDE);
812  double maxang = 2.01*base.max_pixrad();
813  for (int m=0; m<nsamples/10; ++m)
814  {
815  I pix = I(rng.rand_uni()*base.Npix());
816  fix_arr<I,8> nb;
817  vec3 pixpt = base.pix2vec(pix);
818  base.neighbors(pix,nb);
819  for (int n=0; n<8; ++n)
820  if ((nb[n]>=0) && (v_angle(base.pix2vec(nb[n]),pixpt)>maxang))
821  FAIL(cout<<" PROBLEM: nside = "<<nside<<", pix = "<<pix<<endl)
822  }
823  }
824  }
825 
826 void check_swap_scheme()
827  {
828  cout << "testing whether double swap_scheme() returns the original map"
829  << endl << "(for orders 0 to 10)." << endl;
830  for (int order=0; order<=10; ++order)
831  {
832  Healpix_Map<uint8> map(order,NEST);
833  for (int m=0; m<map.Npix(); ++m) map[m]=uint8(m&0xFF);
834  map.swap_scheme();
835  map.swap_scheme();
836  for (int m=0; m<map.Npix(); ++m)
837  if (map[m]!=(m&0xFF))
838  FAIL(cout<<" PROBLEM: order = "<<order<<", pix = "<<m<<endl)
839  }
840  }
841 
842 void check_issue_229 (Healpix_Ordering_Scheme scheme)
843  {
844  cout << "checking issue #229" << endl;
845  int order=8;
846  Healpix_Map<bool> map (order,scheme);
847  map.fill(false);
848  Healpix_Map<vec3> vmap(order,scheme);
849  for (int m=0; m<vmap.Npix(); ++m)
850  vmap[m]=vmap.pix2vec(m);
851  pointing ptg(halfpi-0.1,0);
852  double rad=0.1;
853  auto pixset = map.query_disc(ptg,rad);
854  vec3 vptg=ptg;
855  double cosrad=cos(rad);
856  for (tsize j=0; j<pixset.nranges(); ++j)
857  for (int i=pixset.ivbegin(j); i<pixset.ivend(j); ++i)
858  map[i] = true;
859  for (int i=0; i<map.Npix(); ++i)
860  {
861  bool inside = dotprod(vmap[i],vptg)>cosrad;
862  if (inside^map[i])
863  FAIL(cout << " PROBLEM: issue 229" << endl)
864  }
865  }
866 
867 void check_issue_968 ()
868  {
869  cout << "checking issue #968" << endl;
870  int nside=4;
871  Healpix_Base base (nside,RING,SET_NSIDE);
872  pointing ptg(174*pi/180., 45*pi/180.);
873  vector<int> res;
874  base.query_disc_inclusive (ptg, 9.9*pi/180., res, 4);
875  if (find(res.begin(), res.end(), 190) == res.end())
876  FAIL(cout << " PROBLEM: issue 968" << endl)
877  }
878 
879 void check_query_disc_strict (Healpix_Ordering_Scheme scheme)
880  {
881  cout << "testing whether all pixels found by query_disc() really" << endl
882  << "lie inside the disk (and vice versa)" << endl;
883  cout << "Ordering scheme: " << (scheme==RING ? "RING" : "NEST") << endl;
884  rng.seed(42);
885  for (int order=0; order<=5; ++order)
886  {
887  Healpix_Map<bool> map (order,scheme);
888  map.fill(false);
889  Healpix_Map<vec3> vmap(order,scheme);
890  for (int m=0; m<vmap.Npix(); ++m)
891  vmap[m]=vmap.pix2vec(m);
892  for (int m=0; m<100000; ++m)
893  {
894  pointing ptg;
895  random_dir (ptg);
896  double rad = pi/1 * rng.rand_uni();
897  auto pixset = map.query_disc(ptg,rad);
898  vec3 vptg=ptg;
899  double cosrad=cos(rad);
900  for (tsize j=0; j<pixset.nranges(); ++j)
901  for (int i=pixset.ivbegin(j); i<pixset.ivend(j); ++i)
902  map[i] = true;
903  for (int i=0; i<map.Npix(); ++i)
904  {
905  bool inside = dotprod(vmap[i],vptg)>cosrad;
906  if (inside^map[i])
907  FAIL(cout<<" PROBLEM: order = "<<order<<", ptg = "<<ptg<<endl)
908  }
909  for (tsize j=0; j<pixset.nranges(); ++j)
910  for (int i=pixset.ivbegin(j); i<pixset.ivend(j); ++i)
911  map[i] = false;
912  }
913  }
914  }
915 
916 template<typename I>void check_query_disc()
917  {
918  cout << "checking query_disc() " << bname<I>() << endl;
919  rng.seed(48);
920  int omax=min<int>(20,T_Healpix_Base<I>::order_max);
921  for (int order=0; order<=omax; ++order)
922  {
923  T_Healpix_Base<I> rbase (order,RING), nbase (order,NEST);
924  int niter=max(1,min(1000,100000>>order));
925  for (int m=0; m<niter; ++m)
926  {
927  pointing ptg;
928  random_dir (ptg);
929  double rad = pi/1 * rng.rand_uni();
930  auto pixset = rbase.query_disc(ptg,rad);
931  rangeset<I> pslast=pixset;
932  for (tsize fct=5; fct>0; --fct)
933  {
934  auto psi = rbase.query_disc_inclusive(ptg,rad,fct);
935  if (!psi.contains(pslast))
936  cout << " Potential problem: RING pixel sets inconsistent" << endl;
937  swap(pslast,psi);
938  }
939  I nval = pixset.nval();
940  pixset = nbase.query_disc(ptg,rad);
941  pslast=pixset;
942  for (tsize fct=8; fct>0; fct>>=1)
943  {
944  auto psi = nbase.query_disc_inclusive(ptg,rad,fct);
945  if (!psi.contains(pslast))
946  FAIL(cout << " PROBLEM: NEST pixel sets inconsistent" << endl)
947  swap(pslast,psi);
948  }
949  if (nval!=pixset.nval())
950  FAIL(cout << " PROBLEM: number of pixels different: "
951  << nval << " vs. " << pixset.nval() << endl)
952  }
953  }
954  }
955 template<typename I>void check_query_polygon()
956  {
957  cout << "checking query_polygon() " << bname<I>() << endl;
958  rng.seed(42);
959  int omax=min<int>(20,T_Healpix_Base<I>::order_max);
960  for (int order=0; order<=omax; ++order)
961  {
962  T_Healpix_Base<I> rbase (order,RING), nbase (order,NEST);
963  int niter=max(1,min(1000,100000>>order));
964  for (int m=0; m<niter; ++m)
965  {
966  vector<pointing> corner(3);
967  random_dir(corner[0]); random_dir(corner[1]); random_dir(corner[2]);
968  auto pixset = rbase.query_polygon(corner);
969  I nval = pixset.nval();
970  pixset = nbase.query_polygon(corner);
971  if (nval!=pixset.nval())
972  FAIL(cout << " PROBLEM: number of pixels different: "
973  << nval << " vs. " << pixset.nval() << endl)
974  pixset = rbase.query_polygon_inclusive(corner,4);
975  I nv1=pixset.nval();
976  pixset = nbase.query_polygon_inclusive(corner,4);
977  I nv2=pixset.nval();
978  if (nv1<nv2)
979  FAIL(cout << " PROBLEM: inclusive(RING)<inclusive(NEST): "
980  << nv1 << " vs. " << nv2 << endl)
981  if (nv2<nval)
982  FAIL(cout << " PROBLEM: inclusive(NEST)<non-inclusive: "
983  << nv2 << " vs. " << nval << endl)
984  }
985  }
986  }
987 
988 void helper_oop (int order)
989  {
990  Healpix_Map<double> map (order,RING), map2 (order,NEST), map3 (order,RING);
991  for (int m=0; m<map.Npix(); ++m) map[m] = rng.rand_uni()+0.01;
992  map2.Import(map);
993  map3.Import(map2);
994  for (int m=0; m<map.Npix(); ++m)
995  if (!approx(map[m],map3[m],1e-12))
996  FAIL(cout << "PROBLEM: order = " << order << endl)
997  }
998 void helper_udgrade (int order, Healpix_Ordering_Scheme s1,
1000  {
1001  Healpix_Map<double> map (order,s1), map2 (order+2,s2), map3 (order, s1);
1002  for (int m=0; m<map.Npix(); ++m) map[m] = rng.rand_uni()+0.01;
1003  map2.Import(map);
1004  map3.Import(map2);
1005  for (int m=0; m<map.Npix(); ++m)
1006  if (!approx(map[m],map3[m],1e-12))
1007  FAIL(cout << "PROBLEM: order = " << order << endl)
1008  }
1009 void helper_udgrade2 (int nside)
1010  {
1011  Healpix_Map<double> map (nside,RING,SET_NSIDE), map2 (nside*3,RING,SET_NSIDE),
1012  map3 (nside, RING,SET_NSIDE);
1013  for (int m=0; m<map.Npix(); ++m) map[m] = rng.rand_uni()+0.01;
1014  map2.Import(map);
1015  map3.Import(map2);
1016  for (int m=0; m<map.Npix(); ++m)
1017  if (!approx(map[m],map3[m],1e-12))
1018  FAIL(cout << "PROBLEM: nside = " << nside << endl)
1019  }
1020 
1021 void check_import()
1022  {
1023  cout << "testing out-of-place swapping" << endl;
1024  for (int order=0; order<=7; ++order)
1025  helper_oop(order);
1026  cout << "testing downgrade(upgrade(map)) == map" << endl;
1027  for (int order=0; order<=7; ++order)
1028  {
1029  helper_udgrade(order,RING,RING);
1030  helper_udgrade(order,RING,NEST);
1031  helper_udgrade(order,NEST,NEST);
1032  helper_udgrade(order,NEST,RING);
1033  }
1034  for (int nside=3; nside<500; nside+=nside/2+1)
1035  helper_udgrade2(nside);
1036  }
1037 
1038 void check_average()
1039  {
1040  cout << "testing whether average(map) == average(downgraded map)" << endl;
1041  for (int order=1; order<=10; ++order)
1042  {
1043  Healpix_Map<double> map (order,RING), map2(1,RING);
1044  for (int m=0; m<map.Npix(); ++m)
1045  map[m] = rng.rand_uni()+0.01;
1046  map2.Import(map);
1047  double avg=map.average(), avg2=map2.average();
1048  if (!approx(avg,avg2,1e-13))
1049  FAIL(cout << "PROBLEM: order = " << order << " " << avg/avg2-1 << endl)
1050  }
1051  for (int nside=3; nside<1000; nside += nside/2+1)
1052  {
1053  Healpix_Map<double> map (nside,RING,SET_NSIDE), map2(1,RING,SET_NSIDE);
1054  for (int m=0; m<map.Npix(); ++m)
1055  map[m] = rng.rand_uni()+0.01;
1056  map2.Import(map);
1057  double avg=map.average(), avg2=map2.average();
1058  if (!approx(avg,avg2,1e-13))
1059  FAIL(cout << "PROBLEM: nside = " << nside << " " << avg/avg2-1 << endl)
1060  }
1061  }
1062 
1063 void random_alm (Alm<xcomplex<double> >&almT, Alm<xcomplex<double> >&almG,
1064  Alm<xcomplex<double> >&almC, int lmax, int mmax)
1065  {
1066  almT.Set(lmax,mmax); almG.Set(lmax,mmax); almC.Set(lmax,mmax);
1067 
1068  for (int l=0; l<=lmax; ++l)
1069  {
1070  almT(l,0)=dcomplex(rng.rand_gauss(),0.);
1071  almG(l,0)=dcomplex(rng.rand_gauss(),0.);
1072  almC(l,0)=dcomplex(rng.rand_gauss(),0.);
1073  }
1074 
1075  for (int m=1; m<=mmax; ++m)
1076  for (int l=m; l<=lmax; ++l)
1077  {
1078  almT(l,m).real(rng.rand_gauss()); almT(l,m).imag(rng.rand_gauss());
1079  almG(l,m).real(rng.rand_gauss()); almG(l,m).imag(rng.rand_gauss());
1080  almC(l,m).real(rng.rand_gauss()); almC(l,m).imag(rng.rand_gauss());
1081  }
1082  almG(0,0)=almC(0,0)=almG(1,0)=almC(1,0)=almG(1,1)=almC(1,1)=0;
1083  }
1084 
1085 void random_alm (Alm<xcomplex<double> >&alm, int lmax, int mmax)
1086  {
1087  alm.Set(lmax,mmax);
1088 
1089  for (int l=0; l<=lmax; ++l)
1090  { alm(l,0)=dcomplex(rng.rand_gauss(),0.); }
1091 
1092  for (int m=1; m<=mmax; ++m)
1093  for (int l=m; l<=lmax; ++l)
1094  { alm(l,m).real(rng.rand_gauss()); alm(l,m).imag(rng.rand_gauss()); }
1095  }
1096 
1097 void check_alm (const Alm<xcomplex<double> >&oalm,
1098  const Alm<xcomplex<double> >&alm, double epsilon)
1099  {
1100  for (int m=0; m<=alm.Mmax(); ++m)
1101  for (int l=m; l<=alm.Lmax(); ++l)
1102  {
1103  if (!abs_approx(oalm(l,m).real(),alm(l,m).real(),epsilon))
1104  FAIL(cout << "Problemr " << l << " " << m << endl)
1105  if (!abs_approx(oalm(l,m).imag(),alm(l,m).imag(),epsilon))
1106  FAIL(cout << "Problemi " << l << " " << m << endl)
1107  }
1108  }
1109 
1110 void check_alm2map2alm (int lmax, int mmax, int nside)
1111  {
1112  cout << "testing whether a_lm->map->a_lm returns original a_lm" << endl;
1113  cout << "lmax=" << lmax <<", mmax=" << mmax << ", nside=" << nside << endl;
1114  const double epsilon = 1e-8;
1115  Alm<xcomplex<double> > oalmT(lmax,mmax),almT(lmax,mmax),
1116  oalmG(lmax,mmax),almG(lmax,mmax),oalmC(lmax,mmax),almC(lmax,mmax);
1117  Healpix_Map<double> mapT(nside,RING,SET_NSIDE), mapQ(nside,RING,SET_NSIDE),
1118  mapU(nside,RING,SET_NSIDE);
1119 
1120  const double eps0=1e-11;
1121  const double eps=1e-12;
1122 
1123  random_alm(oalmT,oalmG,oalmC,lmax,mmax);
1124  alm2map(oalmT,mapT);
1125  map2alm_iter2(mapT,almT,eps0,eps0);
1126  check_alm (oalmT, almT, epsilon);
1127 
1128  alm2map_spin(oalmG,oalmC,mapQ,mapU,1);
1129  map2alm_spin_iter2(mapQ,mapU,almG,almC,1,eps,eps);
1130  check_alm (oalmG, almG, epsilon);
1131  check_alm (oalmC, almC, epsilon);
1132 
1133  alm2map_pol(oalmT,oalmG,oalmC,mapT,mapQ,mapU);
1134  map2alm_pol_iter2(mapT,mapQ,mapU,almT,almG,almC,max(eps,eps0),max(eps,eps0));
1135  check_alm (oalmT, almT, epsilon);
1136  check_alm (oalmG, almG, epsilon);
1137  check_alm (oalmC, almC, epsilon);
1138  }
1139 
1140 void check_smooth_alm ()
1141  {
1142  cout << "testing whether unsmooth(smooth(a_lm)) returns a_lm" << endl;
1143  const double epsilon = 1e-14;
1144  const double fwhm = 100.*arcmin2rad;
1145  const int lmax=300, mmax=300;
1146  Alm<xcomplex<double> > oalmT(lmax,mmax),almT(lmax,mmax),
1147  oalmG(lmax,mmax),almG(lmax,mmax),oalmC(lmax,mmax),almC(lmax,mmax);
1148 
1149  random_alm(oalmT,oalmG,oalmC,lmax,mmax);
1150 
1151  almT=oalmT; almG=oalmG; almC=oalmC;
1152  smoothWithGauss (almT, fwhm);
1153  smoothWithGauss (almT, -fwhm);
1154  check_alm (oalmT, almT, epsilon);
1155  almT=oalmT;
1156  smoothWithGauss (almT, almG, almC, fwhm);
1157  smoothWithGauss (almT, almG, almC, -fwhm);
1158  check_alm (oalmT, almT, epsilon);
1159  check_alm (oalmG, almG, epsilon);
1160  check_alm (oalmC, almC, epsilon);
1161  }
1162 
1163 void check_rot_alm ()
1164  {
1165  cout << "testing whether rot^-1(rot(a_lm)) returns a_lm" << endl;
1166  const double epsilon = 2e-13;
1167  const int lmax=300;
1168  Alm<xcomplex<double> > oalm(lmax,lmax),alm(lmax,lmax);
1169 
1170  random_alm(oalm,lmax,lmax);
1171 
1172  alm=oalm;
1173  rotate_alm (alm,3,4,5);
1174  rotate_alm (alm,-5,-4,-3);
1175  check_alm (oalm, alm, epsilon);
1176  }
1177 
1178 double map_residual (const Healpix_Map<double> &a, const Healpix_Map<double> &b)
1179  {
1180  planck_assert(a.conformable(b), "maps are not conformable");
1181  double res=0;
1182  for (int i=0; i<a.Npix(); ++i)
1183  {
1184  double diff=a[i]-b[i];
1185  res+=diff*diff;
1186  }
1187  return res;
1188  }
1189 
1190 void check_ringweights ()
1191  {
1192  cout << "testing the accuracy of ring weights" << endl;
1193  int nside=128;
1194  double dummy;
1195  auto rwgt0=get_ringweights(nside,3*nside,1e-6,3000,dummy);
1196  arr<double> rwgt(2*nside);
1197  for (tsize i=0; i<rwgt.size(); ++i) rwgt[i]=rwgt0[i]+1.;
1198  Alm<xcomplex<double> > alm; random_alm(alm,1.5*nside,0);
1199  Healpix_Map<double> omap(nside,RING,SET_NSIDE),map2(omap);
1200  alm2map(alm,omap);
1201  map2alm(omap,alm,arr<double>(2*nside,1.));
1202  alm2map(alm,map2);
1203  double ressimple = map_residual(omap,map2);
1204  map2alm(omap,alm,rwgt);
1205  alm2map(alm,map2);
1206  double reswgt = map_residual(omap,map2);
1207  double resquot=sqrt(reswgt/ressimple);
1208  if (resquot>1e-5)
1209  FAIL(cout << " PROBLEM with ringweights: resquot = " << resquot << endl)
1210  }
1211 
1212 void check_fullweights ()
1213  {
1214  cout << "testing the accuracy of pixel weights" << endl;
1215  int nside=128;
1216  double dummy;
1217  auto fwgt=get_fullweights(nside,3*nside,1e-6,3000,dummy);
1218  Alm<xcomplex<double> > alm; random_alm(alm,1.5*nside,1.5*nside);
1219  Healpix_Map<double> omap(nside,RING,SET_NSIDE),map2(omap);
1220  alm2map(alm,omap);
1221  map2alm(omap,alm,arr<double>(2*nside,1.));
1222  alm2map(alm,map2);
1223  double ressimple = map_residual(omap,map2);
1224  map2=omap;
1225  apply_fullweights(map2,fwgt);
1226  map2alm(map2,alm,arr<double>(2*nside,1.));
1227  alm2map(alm,map2);
1228  double reswgt = map_residual(omap,map2);
1229  double resquot=sqrt(reswgt/ressimple);
1230  if (resquot>1e-5)
1231  FAIL(cout << " PROBLEM with full weights: resquot = " << resquot << endl)
1232  }
1233 
1234 void check_isqrt()
1235  {
1236  cout << "testing whether isqrt() works reliably" << endl;
1237  uint64 val=uint64(0xF234)<<16, valsq=val*val;
1238  if (isqrt(valsq)!=val) FAIL(cout << "PROBLEM1" << endl)
1239  if (isqrt(valsq-1)!=val-1) FAIL(cout << "PROBLEM2" << endl)
1240  }
1241 
1242 void check_pix2ang_acc()
1243  {
1244  cout << "testing accuracy of pix2ang at the poles" << endl;
1245  for (int m=0; m<=29;++m)
1246  {
1247  Healpix_Base2 base(m,RING);
1248  if (base.pix2ang(1).theta==0.)
1249  FAIL(cout << "PROBLEM: order " << m << endl)
1250  }
1251  }
1252 
1253 const int nsteps=1000000;
1254 
1255 template<typename I>void perf_neighbors(const string &name,
1256  Healpix_Ordering_Scheme scheme)
1257  {
1258  tsize cnt=0;
1259  wallTimers.start(name);
1261  for (int order=0; order<=omax; ++order)
1262  {
1263  T_Healpix_Base<I> base (order,scheme);
1264  I dpix=max(base.Npix()/nsteps,I(1));
1265  fix_arr<I,8> nres;
1266  for (I pix=0; pix<base.Npix(); pix+=dpix)
1267  {
1268  base.neighbors(pix,nres);
1269  ++cnt;
1270  }
1271  }
1272  wallTimers.stop(name);
1273  cout << name << ": " << cnt/wallTimers.acc(name)*1e-6 << "MOps/s" << endl;
1274  }
1275 template<typename I>void perf_pix2ang(const string &name,
1276  Healpix_Ordering_Scheme scheme, double &dummy)
1277  {
1278  tsize cnt=0;
1279  wallTimers.start(name);
1281  for (int order=0; order<=omax; ++order)
1282  {
1283  T_Healpix_Base<I> base (order,scheme);
1284  I dpix=max(base.Npix()/nsteps,I(1));
1285  for (I pix=0; pix<base.Npix(); pix+=dpix)
1286  {
1287  pointing p(base.pix2ang(pix));
1288  dummy+=p.theta+p.phi;
1289  ++cnt;
1290  }
1291  }
1292  wallTimers.stop(name);
1293  cout << name << ": " << cnt/wallTimers.acc(name)*1e-6 << "MOps/s" << endl;
1294  }
1295 template<typename I>void perf_pix2vec(const string &name,
1296  Healpix_Ordering_Scheme scheme, double &dummy)
1297  {
1298  tsize cnt=0;
1299  wallTimers.start(name);
1301  for (int order=0; order<=omax; ++order)
1302  {
1303  T_Healpix_Base<I> base (order,scheme);
1304  I dpix=max(base.Npix()/nsteps,I(1));
1305  for (I pix=0; pix<base.Npix(); pix+=dpix)
1306  {
1307  vec3 v(base.pix2vec(pix));
1308  dummy+=v.x+v.y+v.z;
1309  ++cnt;
1310  }
1311  }
1312  wallTimers.stop(name);
1313  cout << name << ": " << cnt/wallTimers.acc(name)*1e-6 << "MOps/s" << endl;
1314  }
1315 template<typename I>void perf_pix2zphi(const string &name,
1316  Healpix_Ordering_Scheme scheme, double &dummy)
1317  {
1318  tsize cnt=0;
1319  wallTimers.start(name);
1321  for (int order=0; order<=omax; ++order)
1322  {
1323  T_Healpix_Base<I> base (order,scheme);
1324  I dpix=max(base.Npix()/nsteps,I(1));
1325  double z,phi;
1326  for (I pix=0; pix<base.Npix(); pix+=dpix)
1327  {
1328  base.pix2zphi(pix,z,phi);
1329  dummy+=z+phi;
1330  ++cnt;
1331  }
1332  }
1333  wallTimers.stop(name);
1334  cout << name << ": " << cnt/wallTimers.acc(name)*1e-6 << "MOps/s" << endl;
1335  }
1336 template<typename I>void perf_zphi2pix(const string &name,
1337  Healpix_Ordering_Scheme scheme, double &dummy)
1338  {
1339  tsize cnt=0;
1340  wallTimers.start(name);
1342  double dz=2./sqrt(nsteps);
1343  double dph=twopi/sqrt(nsteps);
1344  for (int order=0; order<=omax; ++order)
1345  {
1346  T_Healpix_Base<I> base (order,scheme);
1347  for (double z=-1; z<1; z+=dz)
1348  for (double phi=0; phi<twopi; phi+=dph)
1349  {
1350  dummy+=base.zphi2pix(z,phi);
1351  ++cnt;
1352  }
1353  }
1354  wallTimers.stop(name);
1355  cout << name << ": " << cnt/wallTimers.acc(name)*1e-6 << "MOps/s" << endl;
1356  }
1357 template<typename I>void perf_ang2pix(const string &name,
1358  Healpix_Ordering_Scheme scheme, double &dummy)
1359  {
1360  tsize cnt=0;
1361  wallTimers.start(name);
1363  double dth=pi/sqrt(nsteps);
1364  double dph=twopi/sqrt(nsteps);
1365  for (int order=0; order<=omax; ++order)
1366  {
1367  T_Healpix_Base<I> base (order,scheme);
1368  for (double theta=0; theta<pi; theta+=dth)
1369  for (double phi=0; phi<twopi; phi+=dph)
1370  {
1371  dummy+=base.ang2pix(pointing(theta+1e-15*phi,phi));
1372  ++cnt;
1373  }
1374  }
1375  wallTimers.stop(name);
1376  cout << name << ": " << cnt/wallTimers.acc(name)*1e-6 << "MOps/s" << endl;
1377  }
1378 template<typename I>void perf_ring2nest(const string &name,double &dummy)
1379  {
1380  tsize cnt=0;
1381  wallTimers.start(name);
1383  for (int order=0; order<=omax; ++order)
1384  {
1385  T_Healpix_Base<I> base (order,RING);
1386  I dpix=max(base.Npix()/nsteps,I(1));
1387  for (I pix=0; pix<base.Npix(); pix+=dpix)
1388  {
1389  dummy+=base.ring2nest(pix);
1390  ++cnt;
1391  }
1392  }
1393  wallTimers.stop(name);
1394  cout << name << ": " << cnt/wallTimers.acc(name)*1e-6 << "MOps/s" << endl;
1395  }
1396 template<typename I>void perf_nest2ring(const string &name,double &dummy)
1397  {
1398  tsize cnt=0;
1399  wallTimers.start(name);
1401  for (int order=0; order<=omax; ++order)
1402  {
1403  T_Healpix_Base<I> base (order,RING);
1404  I dpix=max(base.Npix()/nsteps,I(1));
1405  for (I pix=0; pix<base.Npix(); pix+=dpix)
1406  {
1407  dummy+=base.nest2ring(pix);
1408  ++cnt;
1409  }
1410  }
1411  wallTimers.stop(name);
1412  cout << name << ": " << cnt/wallTimers.acc(name)*1e-6 << "MOps/s" << endl;
1413  }
1414 template<typename I>void perf_peano2nest(const string &name,double &dummy)
1415  {
1416  tsize cnt=0;
1417  wallTimers.start(name);
1419  for (int order=0; order<=omax; ++order)
1420  {
1421  T_Healpix_Base<I> base (order,NEST);
1422  I dpix=max(base.Npix()/nsteps,I(1));
1423  for (I pix=0; pix<base.Npix(); pix+=dpix)
1424  {
1425  dummy+=base.peano2nest(pix);
1426  ++cnt;
1427  }
1428  }
1429  wallTimers.stop(name);
1430  cout << name << ": " << cnt/wallTimers.acc(name)*1e-6 << "MOps/s" << endl;
1431  }
1432 template<typename I>void perf_nest2peano(const string &name,double &dummy)
1433  {
1434  tsize cnt=0;
1435  wallTimers.start(name);
1437  for (int order=0; order<=omax; ++order)
1438  {
1439  T_Healpix_Base<I> base (order,NEST);
1440  I dpix=max(base.Npix()/nsteps,I(1));
1441  for (I pix=0; pix<base.Npix(); pix+=dpix)
1442  {
1443  dummy+=base.nest2peano(pix);
1444  ++cnt;
1445  }
1446  }
1447  wallTimers.stop(name);
1448  cout << name << ": " << cnt/wallTimers.acc(name)*1e-6 << "MOps/s" << endl;
1449  }
1450 template<typename I>void perf_query_disc(const string &name,
1451  Healpix_Ordering_Scheme scheme, double &dummy)
1452  {
1453  tsize cnt=0;
1454  T_Healpix_Base<I> base(1024,scheme,SET_NSIDE);
1455  wallTimers.start(name);
1456  for (int m=0; m<1000; ++m)
1457  {
1458  dummy += base.query_disc(vec3(1,0,0),halfpi/9).nranges();
1459  ++cnt;
1460  }
1461  wallTimers.stop(name);
1462  cout << name << ": " << cnt/wallTimers.acc(name)*1e-3 << "kOps/s" << endl;
1463  }
1464 template<typename I>void perf_query_triangle(const string &name,
1465  Healpix_Ordering_Scheme scheme, double &dummy)
1466  {
1467  tsize cnt=0;
1468  T_Healpix_Base<I> base(1024,scheme,SET_NSIDE);
1469  vector<pointing> corner;
1470  corner.push_back(vec3(1,0.01,0.01));
1471  corner.push_back(vec3(0.01,1,0.01));
1472  corner.push_back(vec3(0.01,0.01,1));
1473  wallTimers.start(name);
1474  for (int m=0; m<1000; ++m)
1475  {
1476  dummy += base.query_polygon(corner).nranges();
1477  ++cnt;
1478  }
1479  wallTimers.stop(name);
1480  cout << name << ": " << cnt/wallTimers.acc(name)*1e-3 << "kOps/s" << endl;
1481  }
1482 template<typename I>void perf_query_polygon(const string &name,
1483  Healpix_Ordering_Scheme scheme, double &dummy)
1484  {
1485  tsize cnt=0;
1486  T_Healpix_Base<I> base(1024,scheme,SET_NSIDE);
1487  vector<pointing> corner;
1488  corner.push_back(vec3(1,0.01,0.01));
1489  corner.push_back(vec3(1,1,-0.3));
1490  corner.push_back(vec3(0.01,1,0.01));
1491  corner.push_back(vec3(0.01,0.01,1));
1492  wallTimers.start(name);
1493  for (int m=0; m<1000; ++m)
1494  {
1495  dummy += base.query_polygon(corner).nranges();
1496  ++cnt;
1497  }
1498  wallTimers.stop(name);
1499  cout << name << ": " << cnt/wallTimers.acc(name)*1e-3 << "kOps/s" << endl;
1500  }
1501 
1502 void perftest()
1503  {
1504  double dummy=0;
1505  cout << "Measuring performance of Healpix_Base methods." << endl;
1506  perf_pix2zphi<int> ("pix2zphi (RING):int ",RING,dummy);
1507  perf_pix2zphi<int> ("pix2zphi (NEST):int ",NEST,dummy);
1508  perf_pix2zphi<int64> ("pix2zphi (RING):int64",RING,dummy);
1509  perf_pix2zphi<int64> ("pix2zphi (NEST):int64",NEST,dummy);
1510  perf_zphi2pix<int> ("zphi2pix (RING):int ",RING,dummy);
1511  perf_zphi2pix<int> ("zphi2pix (NEST):int ",NEST,dummy);
1512  perf_zphi2pix<int64> ("zphi2pix (RING):int64",RING,dummy);
1513  perf_zphi2pix<int64> ("zphi2pix (NEST):int64",NEST,dummy);
1514  perf_pix2ang<int> ("pix2ang (RING):int ",RING,dummy);
1515  perf_pix2ang<int> ("pix2ang (NEST):int ",NEST,dummy);
1516  perf_pix2ang<int64> ("pix2ang (RING):int64",RING,dummy);
1517  perf_pix2ang<int64> ("pix2ang (NEST):int64",NEST,dummy);
1518  perf_ang2pix<int> ("ang2pix (RING):int ",RING,dummy);
1519  perf_ang2pix<int> ("ang2pix (NEST):int ",NEST,dummy);
1520  perf_ang2pix<int64> ("ang2pix (RING):int64",RING,dummy);
1521  perf_ang2pix<int64> ("ang2pix (NEST):int64",NEST,dummy);
1522  perf_pix2vec<int> ("pix2vec (RING):int ",RING,dummy);
1523  perf_pix2vec<int> ("pix2vec (NEST):int ",NEST,dummy);
1524  perf_pix2vec<int64> ("pix2vec (RING):int64",RING,dummy);
1525  perf_pix2vec<int64> ("pix2vec (NEST):int64",NEST,dummy);
1526  perf_neighbors<int> ("neighbors(NEST):int ",NEST);
1527  perf_neighbors<int> ("neighbors(RING):int ",RING);
1528  perf_neighbors<int64>("neighbors(NEST):int64",NEST);
1529  perf_neighbors<int64>("neighbors(RING):int64",RING);
1530  perf_ring2nest<int> ("ring2nest :int ",dummy);
1531  perf_ring2nest<int64>("ring2nest :int64",dummy);
1532  perf_nest2ring<int> ("nest2ring :int ",dummy);
1533  perf_nest2ring<int64>("nest2ring :int64",dummy);
1534  perf_peano2nest<int> ("peano2nest :int ",dummy);
1535  perf_peano2nest<int64>("peano2nest :int64",dummy);
1536  perf_nest2peano<int> ("nest2peano :int ",dummy);
1537  perf_nest2peano<int64>("nest2peano :int64",dummy);
1538  perf_query_disc<int> ("query_disc (RING):int ",RING,dummy);
1539  perf_query_disc<int> ("query_disc (NEST):int ",NEST,dummy);
1540  perf_query_disc<int64> ("query_disc (RING):int64",RING,dummy);
1541  perf_query_disc<int64> ("query_disc (NEST):int64",NEST,dummy);
1542  perf_query_triangle<int> ("query_triangle(RING):int ",RING,dummy);
1543  perf_query_triangle<int> ("query_triangle(NEST):int ",NEST,dummy);
1544  perf_query_triangle<int64>("query_triangle(RING):int64",RING,dummy);
1545  perf_query_triangle<int64>("query_triangle(NEST):int64",NEST,dummy);
1546  perf_query_polygon<int> ("query_polygon (RING):int ",RING,dummy);
1547  perf_query_polygon<int> ("query_polygon (NEST):int ",NEST,dummy);
1548  perf_query_polygon<int64> ("query_polygon (RING):int64",RING,dummy);
1549  perf_query_polygon<int64> ("query_polygon (NEST):int64",NEST,dummy);
1550 
1551  if (dummy<0) cout << dummy << endl;
1552  }
1553 
1554 } // unnamed namespace
1555 
1556 int main(int argc, const char **argv)
1557  {
1558  module_startup ("hpxtest",argc,argv,1,"");
1559  perftest();
1560  check_compress<int>();
1561  check_compress<unsigned>();
1562  check_compress<int64>();
1563  check_compress<uint64>();
1564  check_Moc<int>();
1565  check_Moc<int64>();
1566  check_rangeset<int>();
1567  check_rangeset<int64>();
1568  check_crangeset<int>();
1569  check_crangeset<int64>();
1570  check_isqrt();
1571  check_pix2ang_acc();
1572  check_smooth_alm();
1573  check_rot_alm();
1574  check_alm2map2alm(620,620,256);
1575  check_alm2map2alm(620,2,256);
1576  check_average();
1577  check_import();
1578  check_ringnestring<int>();
1579  check_ringnestring<int64>();
1580  check_nestpeanonest<int>();
1581  check_nestpeanonest<int64>();
1582  check_pixzphipix<int>();
1583  check_pixzphipix<int64>();
1584  check_zphipixzphi<int>();
1585  check_zphipixzphi<int64>();
1586  check_pixangpix<int>();
1587  check_pixangpix<int64>();
1588  check_neighbors<int>();
1589  check_neighbors<int64>();
1590  check_swap_scheme();
1591  check_query_disc_strict(RING);
1592  check_query_disc_strict(NEST);
1593  check_issue_229(RING);
1594  check_issue_229(NEST);
1595  check_query_disc<int>();
1596  check_query_disc<int64>();
1597  check_query_polygon<int>();
1598  check_query_polygon<int64>();
1599  check_ringweights();
1600  check_fullweights();
1601  check_issue_968();
1602 #ifdef UNITTESTS
1603  if (errcount>0) planck_fail("unit test errors");
1604 #endif
1605  return 0;
1606  }
vector< double > get_fullweights(int nside, int lmax, double epsilon, int itmax, double &epsilon_out)
Definition: alm.h:88
Healpix_Ordering_Scheme
void map2alm(const Healpix_Map< T > &map, Alm< xcomplex< T > > &alm, const arr< double > &weight, bool add_alm)
void apply_fullweights(Healpix_Map< T > &map, const std::vector< double > &wgt)
void alm2map_pol(const Alm< xcomplex< T > > &almT, const Alm< xcomplex< T > > &almG, const Alm< xcomplex< T > > &almC, Healpix_Map< T > &mapT, Healpix_Map< T > &mapQ, Healpix_Map< T > &mapU, bool add_map)
void alm2map(const Alm< xcomplex< T > > &alm, Healpix_Map< T > &map, bool add_map)
bool conformable(const T_Healpix_Base &other) const
Definition: healpix_base.h:435
vector< double > get_ringweights(int nside, int lmax, double epsilon, int itmax, double &epsilon_out)
I Npix() const
Definition: healpix_base.h:429

Generated on Wed Nov 13 2024 12:18:30 for Healpix C++