Skip to content

Commit eaf010b

Browse files
df7cbmsdemlei
authored andcommitted
1 parent 6eabeb4 commit eaf010b

File tree

6 files changed

+630
-0
lines changed

6 files changed

+630
-0
lines changed

healpix_bare/LICENSE

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
Copyright (C) 1997-2019 Krzysztof M. Gorski, Eric Hivon, Martin Reinecke,
2+
Benjamin D. Wandelt, Anthony J. Banday,
3+
Matthias Bartelmann,
4+
Reza Ansari & Kenneth M. Ganga
5+
6+
Redistribution and use in source and binary forms, with or without modification,
7+
are permitted provided that the following conditions are met:
8+
9+
* Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
* Redistributions in binary form must reproduce the above copyright notice, this
13+
list of conditions and the following disclaimer in the documentation and/or
14+
other materials provided with the distribution.
15+
16+
* Neither the name of the copyright holder nor the names of its contributors may
17+
be used to endorse or promote products derived from this software without
18+
specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
24+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

healpix_bare/NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Version 1.0 (March 2019):
2+
initial release

healpix_bare/README

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
This package implements a small subset of routines for working with the
2+
HEALPix tesselation of the sphere.
3+
4+
For information about HEALPix, see the publication by
5+
K.M. Gorski et al., 2005, Ap.J., 622, p.759
6+
(http://adsabs.harvard.edu/abs/2005ApJ...622..759G)
7+
More comprehensive software packages supporting HEALPix, as well as extensive
8+
documentation and references, are available at
9+
https://healpix.sourceforge.io/.
10+
11+
12+
Compilation
13+
===========
14+
15+
gcc -O2 healpix_bare.c -std=c99 test.c -lm
16+
clang -O2 healpix_bare.c -std=c99 test.c -lm
17+
icc -O2 healpix_bare.c -std=c99 test.c -lm
18+
19+
20+
Notes
21+
=====
22+
23+
This package is designed to cover a small set of frequently used HEALPix-related
24+
routines, which are implemented with a focus on robustness, accuracy and clarity.
25+
They have good performance, but are not heavily tuned to keep the code simple -
26+
the full-featured, GPL-licensed Healpix Fortran and C++ libraries (available
27+
via the link above) will be more efficient in most situations.
28+
29+
The motivation for this package is to give developers of BSD-licensed
30+
Healpix-related codes a reliable starting point, so that they don't have to
31+
re-implement the central algorithms (like conversions between pixel index and
32+
angular coordinates), which are nontrivial to do correctly for all corner cases.
33+
34+
35+
Acknowledgements
36+
================
37+
38+
If you are using this code in your own packages, please consider citing
39+
the original paper in your publications:
40+
41+
K.M. Gorski et al., 2005, Ap.J., 622, p.759
42+
(http://adsabs.harvard.edu/abs/2005ApJ...622..759G)

healpix_bare/healpix_bare.c

+310
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
/* -----------------------------------------------------------------------------
2+
*
3+
* Copyright (C) 1997-2019 Krzysztof M. Gorski, Eric Hivon, Martin Reinecke,
4+
* Benjamin D. Wandelt, Anthony J. Banday,
5+
* Matthias Bartelmann,
6+
* Reza Ansari & Kenneth M. Ganga
7+
*
8+
* Implementation of the Healpix bare bones C library
9+
*
10+
* Licensed under a 3-clause BSD style license - see LICENSE
11+
*
12+
* For more information on HEALPix and additional software packages, see
13+
* https://healpix.sourceforge.io/
14+
*
15+
* If you are using this code in your own packages, please consider citing
16+
* the original paper in your publications:
17+
* K.M. Gorski et al., 2005, Ap.J., 622, p.759
18+
* (http://adsabs.harvard.edu/abs/2005ApJ...622..759G)
19+
*
20+
*----------------------------------------------------------------------------*/
21+
22+
#include <math.h>
23+
#include "healpix_bare.h"
24+
25+
#define pi 3.141592653589793238462643383279502884197
26+
27+
static const int jrll[] = { 2,2,2,2,3,3,3,3,4,4,4,4 };
28+
static const int jpll[] = { 1,3,5,7,0,2,4,6,1,3,5,7 };
29+
30+
/* conversions between continuous coordinate systems */
31+
32+
typedef struct { double z, s, phi; } tloc;
33+
34+
/*! A structure describing the continuous Healpix coordinate system.
35+
\a f takes values in [0;11], \a x and \a y lie in [0.0; 1.0]. */
36+
typedef struct { double x, y; int32_t f; } t_hpc;
37+
38+
static t_hpc loc2hpc (tloc loc)
39+
{
40+
double za = fabs(loc.z);
41+
double x = loc.phi*(1./(2.*pi));
42+
if (x<0.)
43+
x += (int64_t)x + 1.;
44+
else if (x>=1.)
45+
x -= (int64_t)x;
46+
double tt = 4.*x;
47+
48+
if (za<=2./3.) /* Equatorial region */
49+
{
50+
double temp1 = 0.5+tt; // [0.5; 4.5)
51+
double temp2 = loc.z*0.75; // [-0.5; +0.5]
52+
double jp = temp1-temp2; /* index of ascending edge line */ // [0; 5)
53+
double jm = temp1+temp2; /* index of descending edge line */ // [0; 5)
54+
int ifp = (int)jp; /* in {0,4} */
55+
int ifm = (int)jm;
56+
return (t_hpc){jm-ifm, 1+ifp - jp,
57+
(ifp==ifm) ? (ifp|4) : ((ifp<ifm) ? ifp : (ifm+8))};
58+
}
59+
int64_t ntt = (int64_t)tt;
60+
if (ntt>=4) ntt=3;
61+
double tp = tt-ntt; // [0;1)
62+
double tmp = loc.s/sqrt((1.+za)*(1./3.)); // FIXME optimize!
63+
64+
double jp = tp*tmp; /* increasing edge line index */
65+
double jm = (1.0-tp)*tmp; /* decreasing edge line index */
66+
if (jp>1.) jp = 1.; /* for points too close to the boundary */
67+
if (jm>1.) jm = 1.;
68+
return (loc.z >= 0) ? (t_hpc){1.-jm, 1.-jp, ntt}
69+
: (t_hpc){jp, jm, ntt+8};
70+
}
71+
72+
static tloc hpc2loc (t_hpc hpc)
73+
{
74+
double jr = jrll[hpc.f] - hpc.x - hpc.y;
75+
if (jr<1.)
76+
{
77+
double tmp = jr*jr*(1./3.);
78+
double z = 1. - tmp;
79+
double s = sqrt(tmp*(2.-tmp));
80+
double phi = (pi*0.25)*(jpll[hpc.f] + (hpc.x-hpc.y)/jr);
81+
return (tloc){z,s,phi};
82+
}
83+
else if (jr>3.)
84+
{
85+
jr = 4.-jr;
86+
double tmp = jr*jr*(1./3.);
87+
double z = tmp - 1.;
88+
double s = sqrt(tmp*(2.-tmp));
89+
double phi = (pi*0.25)*(jpll[hpc.f] + (hpc.x-hpc.y)/jr);
90+
return (tloc){z,s,phi};
91+
}
92+
else
93+
{
94+
double z = (2.-jr)*(2./3.);
95+
double s = sqrt((1.+z)*(1.-z));
96+
double phi = (pi*0.25)*(jpll[hpc.f] + hpc.x - hpc.y);
97+
return (tloc){z,s,phi};
98+
}
99+
}
100+
101+
static tloc ang2loc(t_ang ang)
102+
{
103+
double cth=cos(ang.theta), sth=sin(ang.theta);
104+
if (sth<0) { sth=-sth; ang.phi+=pi; }
105+
return (tloc){cth, sth, ang.phi};
106+
}
107+
108+
static t_ang loc2ang(tloc loc)
109+
{ return (t_ang){atan2(loc.s,loc.z), loc.phi}; }
110+
111+
static tloc vec2loc(t_vec vec)
112+
{
113+
double vlen=sqrt(vec.x*vec.x+vec.y*vec.y+vec.z*vec.z);
114+
double cth = vec.z/vlen;
115+
double sth = sqrt(vec.x*vec.x+vec.y*vec.y)/vlen;
116+
return (tloc){cth,sth,atan2(vec.y,vec.x)};
117+
}
118+
119+
static t_vec loc2vec(tloc loc)
120+
{ return (t_vec){loc.s*cos(loc.phi), loc.s*sin(loc.phi), loc.z}; }
121+
122+
t_vec ang2vec(t_ang ang)
123+
{ return loc2vec(ang2loc(ang)); }
124+
125+
t_ang vec2ang(t_vec vec)
126+
{
127+
return (t_ang) {atan2(sqrt(vec.x*vec.x+vec.y*vec.y),vec.z),
128+
atan2(vec.y,vec.x)};
129+
}
130+
131+
/* conversions between discrete coordinate systems */
132+
133+
static int64_t isqrt(int64_t v)
134+
{
135+
int64_t res = sqrt(v+0.5);
136+
if (v<((int64_t)(1)<<50)) return res;
137+
if (res*res>v)
138+
--res;
139+
else if ((res+1)*(res+1)<=v)
140+
++res;
141+
return res;
142+
}
143+
144+
static int64_t spread_bits (int64_t v)
145+
{
146+
int64_t res = v & 0xffffffff;
147+
res = (res^(res<<16)) & 0x0000ffff0000ffff;
148+
res = (res^(res<< 8)) & 0x00ff00ff00ff00ff;
149+
res = (res^(res<< 4)) & 0x0f0f0f0f0f0f0f0f;
150+
res = (res^(res<< 2)) & 0x3333333333333333;
151+
res = (res^(res<< 1)) & 0x5555555555555555;
152+
return res;
153+
}
154+
155+
static int64_t compress_bits (int64_t v)
156+
{
157+
int64_t res = v & 0x5555555555555555;
158+
res = (res^(res>> 1)) & 0x3333333333333333;
159+
res = (res^(res>> 2)) & 0x0f0f0f0f0f0f0f0f;
160+
res = (res^(res>> 4)) & 0x00ff00ff00ff00ff;
161+
res = (res^(res>> 8)) & 0x0000ffff0000ffff;
162+
res = (res^(res>>16)) & 0x00000000ffffffff;
163+
return res;
164+
}
165+
166+
/*! A structure describing the discrete Healpix coordinate system.
167+
\a f takes values in [0;11], \a x and \a y lie in [0; nside[. */
168+
typedef struct { int64_t x, y; int32_t f; } t_hpd;
169+
170+
static int64_t hpd2nest (int64_t nside, t_hpd hpd)
171+
{ return (hpd.f*nside*nside) + spread_bits(hpd.x) + (spread_bits(hpd.y)<<1); }
172+
173+
static t_hpd nest2hpd (int64_t nside, int64_t pix)
174+
{
175+
int64_t npface_=nside*nside, p2=pix&(npface_-1);
176+
return (t_hpd){compress_bits(p2), compress_bits(p2>>1), pix/npface_};
177+
}
178+
179+
static int64_t hpd2ring (int64_t nside_, t_hpd hpd)
180+
{
181+
int64_t nl4 = 4*nside_;
182+
int64_t jr = (jrll[hpd.f]*nside_) - hpd.x - hpd.y - 1;
183+
184+
if (jr<nside_)
185+
{
186+
int64_t jp = (jpll[hpd.f]*jr + hpd.x - hpd.y + 1) / 2;
187+
jp = (jp>nl4) ? jp-nl4 : ((jp<1) ? jp+nl4 : jp);
188+
return 2*jr*(jr-1) + jp - 1;
189+
}
190+
else if (jr > 3*nside_)
191+
{
192+
jr = nl4-jr;
193+
int64_t jp = (jpll[hpd.f]*jr + hpd.x - hpd.y + 1) / 2;
194+
jp = (jp>nl4) ? jp-nl4 : ((jp<1) ? jp+nl4 : jp);
195+
return 12*nside_*nside_ - 2*(jr+1)*jr + jp - 1;
196+
}
197+
else
198+
{
199+
int64_t jp = (jpll[hpd.f]*nside_ + hpd.x - hpd.y + 1 + ((jr-nside_)&1)) / 2;
200+
jp = (jp>nl4) ? jp-nl4 : ((jp<1) ? jp+nl4 : jp);
201+
return 2*nside_*(nside_-1) + (jr-nside_)*nl4 + jp - 1;
202+
}
203+
}
204+
205+
static t_hpd ring2hpd (int64_t nside_, int64_t pix)
206+
{
207+
int64_t ncap_=2*nside_*(nside_-1);
208+
int64_t npix_=12*nside_*nside_;
209+
210+
if (pix<ncap_) /* North Polar cap */
211+
{
212+
int64_t iring = (1+isqrt(1+2*pix))>>1; /* counted from North pole */
213+
int64_t iphi = (pix+1) - 2*iring*(iring-1);
214+
int64_t face = (iphi-1)/iring;
215+
int64_t irt = iring - (jrll[face]*nside_) + 1;
216+
int64_t ipt = 2*iphi- jpll[face]*iring -1;
217+
if (ipt>=2*nside_) ipt-=8*nside_;
218+
return (t_hpd) {(ipt-irt)>>1, (-(ipt+irt))>>1, face};
219+
}
220+
else if (pix<(npix_-ncap_)) /* Equatorial region */
221+
{
222+
int64_t ip = pix - ncap_;
223+
int64_t iring = (ip/(4*nside_)) + nside_; /* counted from North pole */
224+
int64_t iphi = (ip%(4*nside_)) + 1;
225+
int64_t kshift = (iring+nside_)&1;
226+
int64_t ire = iring-nside_+1;
227+
int64_t irm = 2*nside_+2-ire;
228+
int64_t ifm = (iphi - ire/2 + nside_ -1) / nside_;
229+
int64_t ifp = (iphi - irm/2 + nside_ -1) / nside_;
230+
int64_t face = (ifp==ifm) ? (ifp|4) : ((ifp<ifm) ? ifp : (ifm+8));
231+
int64_t irt = iring - (jrll[face]*nside_) + 1;
232+
int64_t ipt = 2*iphi- jpll[face]*nside_ - kshift -1;
233+
if (ipt>=2*nside_) ipt-=8*nside_;
234+
return (t_hpd) {(ipt-irt)>>1, (-(ipt+irt))>>1, face};
235+
}
236+
else /* South Polar cap */
237+
{
238+
int64_t ip = npix_ - pix;
239+
int64_t iring = (1+isqrt(2*ip-1))>>1; /* counted from South pole */
240+
int64_t iphi = 4*iring + 1 - (ip - 2*iring*(iring-1));
241+
int64_t face=8+(iphi-1)/iring;
242+
int64_t irt = 4*nside_ - iring - (jrll[face]*nside_) + 1;
243+
int64_t ipt = 2*iphi- jpll[face]*iring -1;
244+
if (ipt>=2*nside_) ipt-=8*nside_;
245+
return (t_hpd) {(ipt-irt)>>1, (-(ipt+irt))>>1, face};
246+
}
247+
}
248+
249+
int64_t nest2ring(int64_t nside, int64_t ipnest)
250+
{
251+
if ((nside&(nside-1))!=0) return -1;
252+
return hpd2ring (nside, nest2hpd (nside, ipnest));
253+
}
254+
255+
int64_t ring2nest(int64_t nside, int64_t ipring)
256+
{
257+
if ((nside&(nside-1))!=0) return -1;
258+
return hpd2nest (nside, ring2hpd (nside, ipring));
259+
}
260+
261+
/* mixed conversions */
262+
263+
static t_hpd loc2hpd (int64_t nside_, tloc loc)
264+
{
265+
t_hpc tmp = loc2hpc(loc);
266+
return (t_hpd){(tmp.x*nside_), (tmp.y*nside_), tmp.f};
267+
}
268+
269+
static tloc hpd2loc (int64_t nside_, t_hpd hpd)
270+
{
271+
double xns = 1./nside_;
272+
t_hpc tmp = (t_hpc){(hpd.x+0.5)*xns,(hpd.y+0.5)*xns,hpd.f};
273+
return hpc2loc(tmp);
274+
}
275+
276+
int64_t npix2nside(int64_t npix)
277+
{
278+
int64_t res = isqrt(npix/12);
279+
return (res*res*12==npix) ? res : -1;
280+
}
281+
282+
int64_t nside2npix(int64_t nside)
283+
{ return 12*nside*nside; }
284+
285+
double vec_angle(t_vec v1, t_vec v2)
286+
{
287+
t_vec cross = { v1.y*v2.z - v1.z*v2.y,
288+
v1.z*v2.x - v1.x*v2.z,
289+
v1.x*v2.y - v1.y*v2.x };
290+
double len_cross = sqrt(cross.x*cross.x + cross.y*cross.y + cross.z*cross.z);
291+
double dot = v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
292+
return atan2 (len_cross, dot);
293+
}
294+
295+
int64_t ang2ring(int64_t nside, t_ang ang)
296+
{ return hpd2ring(nside, loc2hpd(nside, ang2loc(ang))); }
297+
int64_t ang2nest(int64_t nside, t_ang ang)
298+
{ return hpd2nest(nside, loc2hpd(nside, ang2loc(ang))); }
299+
int64_t vec2ring(int64_t nside, t_vec vec)
300+
{ return hpd2ring(nside, loc2hpd(nside, vec2loc(vec))); }
301+
int64_t vec2nest(int64_t nside, t_vec vec)
302+
{ return hpd2nest(nside, loc2hpd(nside, vec2loc(vec))); }
303+
t_ang ring2ang(int64_t nside, int64_t ipix)
304+
{ return loc2ang(hpd2loc(nside, ring2hpd(nside, ipix))); }
305+
t_ang nest2ang(int64_t nside, int64_t ipix)
306+
{ return loc2ang(hpd2loc(nside, nest2hpd(nside, ipix))); }
307+
t_vec ring2vec(int64_t nside, int64_t ipix)
308+
{ return loc2vec(hpd2loc(nside, ring2hpd(nside, ipix))); }
309+
t_vec nest2vec(int64_t nside, int64_t ipix)
310+
{ return loc2vec(hpd2loc(nside, nest2hpd(nside, ipix))); }

0 commit comments

Comments
 (0)