@hscmap/healpix
Version:
## Introduction
627 lines (626 loc) • 21.5 kB
JavaScript
"use strict";
/**
* # API Reference
*
* This package based on this paper: [Gorski (2005)](http://iopscience.iop.org/article/10.1086/427976/pdf).
*
* The key things to understand the implementation are:
* - Spherical coordinates in different representations such as `(alpha, delta)`
* or `(theta, phi)` or `(X, Y, z)` are always normalised to `(z, a)`.
* - The HEALPix spherical projection is used to map to `(t, u)` (see `za2tu` and `tu2za`).
* See Section 4.4 and Figure 5 in the paper, where `(t, u)` is called `(x_s, y_s)`.
*
* - A simple affine transformation is used to map to `(f, x, y)` (see `tu2fxy` and `fxy2tu`),
* where `f = {0 .. 11}` is the base pixel index and `(x, y)` is the position
* within the base pixel in the (north-east, north-west) direction
* and `(0, 0)` in the south corner.
* - From `(f, x, y)`, the HEALPix pixel index in the "nested" scheme
* is related via `fxy2nest` and `nest2fxy`, and in the "ring" scheme
* via `fxy2ring` and `ring2fxy` in a relatively simple equations.
*
* To summarise: there are two geometrical transformations:
* `(z, a)` <-> `(t, u)` is the HEALPix spherical projection,
* and `(t, u)` <-> `(f, x, y)` is a 45 deg rotation and scaling for each
* of the 12 base pixels, so that HEALPix pixels in `(x, y)` are unit squares,
* and pixel index compuatations are relatively straightforward,
* both in the "nested" and "ring" pixelisation scheme.
*
* ## Notations
*
* <pre>
* theta : colatitude (pi/2 - delta) [0 , pi]
* phi : longitude (alpha) [0, 2 pi)
* t : coord. of x-axis in spherical projection [0, 2 pi)
* u : coord. of y-axis in spherical projection [-pi/2, pi/2]
* z : cos(theta) [-1, 1]
* X : sin(theta) * cos(phi) [-1, 1]
* Y : sin(theta) * sin(phi) [-1, 1]
* a : phi [0, 2 pi)
* f : base pixel index {0 .. 11}
* x : north-east index in base pixel [0, nside)
* y : north-west index in base pixel [0, nside)
* p : north-east axis in base pixel [0, 1)
* q : north-west axis in base pixel [0, 1)
* j : pixel-in-ring index polar cap: {1 .. 4 i}
* equatorial belt: {1 .. 4 nside}
* i : ring index {1 .. 4 nside - 1}
* </pre>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniq2orderpix = exports.orderpix2uniq = exports.fxy2tu = exports.bit_decombine = exports.bit_combine = exports.fxy2nest = exports.vec2ang = exports.ang2vec = exports.tu2za = exports.za2tu = exports.tu2fxy = exports.pixcoord2vec_ring = exports.pixcoord2vec_nest = exports.nside2resol = exports.nside2pixarea = exports.corners_ring = exports.corners_nest = exports.max_pixrad = exports.query_disc_inclusive_ring = exports.query_disc_inclusive_nest = exports.pix2ang_ring = exports.pix2vec_ring = exports.pix2ang_nest = exports.pix2vec_nest = exports.ring2fxy = exports.ring2nest = exports.nest2ring = exports.ang2pix_ring = exports.ang2pix_nest = exports.vec2pix_ring = exports.vec2pix_nest = exports.nside2npix = exports.nside2order = exports.order2nside = void 0;
function order2nside(order) {
return 1 << order;
}
exports.order2nside = order2nside;
function nside2order(nside) {
return ilog2(nside);
}
exports.nside2order = nside2order;
function nside2npix(nside) {
return 12 * nside * nside;
}
exports.nside2npix = nside2npix;
function vec2pix_nest(nside, v) {
var _a = vec2za(v[0], v[1], v[2]), z = _a.z, a = _a.a;
return za2pix_nest(nside, z, a);
}
exports.vec2pix_nest = vec2pix_nest;
function vec2pix_ring(nside, v) {
var _a = vec2za(v[0], v[1], v[2]), z = _a.z, a = _a.a;
return nest2ring(nside, za2pix_nest(nside, z, a));
}
exports.vec2pix_ring = vec2pix_ring;
function ang2pix_nest(nside, theta, phi) {
var z = Math.cos(theta);
return za2pix_nest(nside, z, phi);
}
exports.ang2pix_nest = ang2pix_nest;
function ang2pix_ring(nside, theta, phi) {
var z = Math.cos(theta);
return nest2ring(nside, za2pix_nest(nside, z, phi));
}
exports.ang2pix_ring = ang2pix_ring;
function nest2ring(nside, ipix) {
var _a = nest2fxy(nside, ipix), f = _a.f, x = _a.x, y = _a.y;
return fxy2ring(nside, f, x, y);
}
exports.nest2ring = nest2ring;
function ring2nest(nside, ipix) {
if (nside == 1) {
return ipix;
}
var _a = ring2fxy(nside, ipix), f = _a.f, x = _a.x, y = _a.y;
return fxy2nest(nside, f, x, y);
}
exports.ring2nest = ring2nest;
function ring2fxy(nside, ipix) {
var polar_lim = 2 * nside * (nside - 1);
if (ipix < polar_lim) { // north polar cap
var i = Math.floor((Math.sqrt(1 + 2 * ipix) + 1) / 2);
var j = ipix - 2 * i * (i - 1);
var f = Math.floor(j / i);
var k = j % i;
var x = nside - i + k;
var y = nside - 1 - k;
return { f: f, x: x, y: y };
}
if (ipix < polar_lim + 8 * nside * nside) { // equatorial belt
var k = ipix - polar_lim;
var ring = 4 * nside;
var i = nside - Math.floor(k / ring);
var s = i % 2 == 0 ? 1 : 0;
var j = 2 * (k % ring) + s;
var jj = j - 4 * nside;
var ii = i + 5 * nside - 1;
var pp = (ii + jj) / 2;
var qq = (ii - jj) / 2;
var PP = Math.floor(pp / nside);
var QQ = Math.floor(qq / nside);
var V = 5 - (PP + QQ);
var H = PP - QQ + 4;
var f = 4 * V + (H >> 1) % 4;
var x = pp % nside;
var y = qq % nside;
return { f: f, x: x, y: y };
}
else { // south polar cap
var p = 12 * nside * nside - ipix - 1;
var i = Math.floor((Math.sqrt(1 + 2 * p) + 1) / 2);
var j = p - 2 * i * (i - 1);
var f = 11 - Math.floor(j / i);
var k = j % i;
var x = i - k - 1;
var y = k;
return { f: f, x: x, y: y };
}
}
exports.ring2fxy = ring2fxy;
function pix2vec_nest(nside, ipix) {
var _a = nest2fxy(nside, ipix), f = _a.f, x = _a.x, y = _a.y;
var _b = fxy2tu(nside, f, x, y), t = _b.t, u = _b.u;
var _c = tu2za(t, u), z = _c.z, a = _c.a;
return za2vec(z, a);
}
exports.pix2vec_nest = pix2vec_nest;
function pix2ang_nest(nside, ipix) {
var _a = nest2fxy(nside, ipix), f = _a.f, x = _a.x, y = _a.y;
var _b = fxy2tu(nside, f, x, y), t = _b.t, u = _b.u;
var _c = tu2za(t, u), z = _c.z, a = _c.a;
return { theta: Math.acos(z), phi: a };
}
exports.pix2ang_nest = pix2ang_nest;
function pix2vec_ring(nside, ipix) {
return pix2vec_nest(nside, ring2nest(nside, ipix));
}
exports.pix2vec_ring = pix2vec_ring;
function pix2ang_ring(nside, ipix) {
return pix2ang_nest(nside, ring2nest(nside, ipix));
}
exports.pix2ang_ring = pix2ang_ring;
// TODO: cleanup
function query_disc_inclusive_nest(nside, v, radius, cb) {
if (radius > PI_2) {
throw new Error("query_disc: radius must < PI/2");
}
var pixrad = max_pixrad(nside);
var d = PI_4 / nside;
var _a = vec2za(v[0], v[1], v[2]), z0 = _a.z, a0 = _a.a; // z0 = cos(theta)
var sin_t = Math.sqrt(1 - z0 * z0);
var cos_r = Math.cos(radius); // r := radius
var sin_r = Math.sin(radius);
var z1 = z0 * cos_r + sin_t * sin_r; // cos(theta - r)
var z2 = z0 * cos_r - sin_t * sin_r; // cos(theta + r)
var u1 = za2tu(z1, 0).u;
var u2 = za2tu(z2, 0).u;
var cover_north_pole = sin_t * cos_r - z0 * sin_r < 0; // sin(theta - r) < 0
var cover_south_pole = sin_t * cos_r + z0 * sin_r < 0; // sin(theta - r) < 0
var i1 = Math.floor((PI_2 - u1) / d);
var i2 = Math.floor((PI_2 - u2) / d + 1);
if (cover_north_pole) {
++i1;
for (var i = 1; i <= i1; ++i)
walk_ring(nside, i, cb);
++i1;
}
if (i1 == 0) {
walk_ring(nside, 1, cb);
i1 = 2;
}
if (cover_south_pole) {
--i2;
for (var i = i2; i <= 4 * nside - 1; ++i)
walk_ring(nside, i, cb);
--i2;
}
if (i2 == 4 * nside) {
walk_ring(nside, 4 * nside - 1, cb);
i2 = 4 * nside - 2;
}
var theta = Math.acos(z0);
for (var i = i1; i <= i2; ++i)
walk_ring_around(nside, i, a0, theta, radius + pixrad, function (ipix) {
if (angle(pix2vec_nest(nside, ipix), v) <= radius + pixrad)
cb(ipix);
});
}
exports.query_disc_inclusive_nest = query_disc_inclusive_nest;
function query_disc_inclusive_ring(nside, v, radius, cb_ring) {
return query_disc_inclusive_nest(nside, v, radius, function (ipix) {
cb_ring(nest2ring(nside, ipix));
});
}
exports.query_disc_inclusive_ring = query_disc_inclusive_ring;
function max_pixrad(nside) {
var unit = PI_4 / nside;
return angle(tu2vec(unit, nside * unit), tu2vec(unit, (nside + 1) * unit));
}
exports.max_pixrad = max_pixrad;
function angle(a, b) {
return 2 * Math.asin(Math.sqrt(distance2(a, b)) / 2);
}
function tu2vec(t, u) {
var _a = tu2za(t, u), z = _a.z, a = _a.a;
return za2vec(z, a);
}
function distance2(a, b) {
var dx = a[0] - b[0];
var dy = a[1] - b[1];
var dz = a[2] - b[2];
return dx * dx + dy * dy + dz * dz;
}
function walk_ring_around(nside, i, a0, theta, r, cb) {
if (theta < r || theta + r > PI)
return walk_ring(nside, i, cb);
var u = PI_4 * (2 - i / nside);
var z = tu2za(PI_4, u).z;
var st = Math.sin(theta);
var ct = Math.cos(theta);
var sr = Math.sin(r);
var cr = Math.cos(r);
var w = Math.atan2(Math.sqrt(-square(z - ct * cr) / (square(st) * sr * sr) + 1) * sr, (-z * ct + cr) / st);
if (w >= PI)
return walk_ring(nside, i, cb);
var t1 = center_t(nside, i, za2tu(z, wrap(a0 - w, PI2)).t);
var t2 = center_t(nside, i, za2tu(z, wrap(a0 + w, PI2)).t);
var begin = tu2fxy(nside, t1, u);
var end = right_next_pixel(nside, tu2fxy(nside, t2, u));
for (var s = begin; !fxy_compare(s, end); s = right_next_pixel(nside, s)) {
cb(fxy2nest(nside, s.f, s.x, s.y));
}
}
function center_t(nside, i, t) {
var d = PI_4 / nside;
t /= d;
t = (((t + i % 2) >> 1) << 1) + 1 - i % 2;
t *= d;
return t;
}
function walk_ring(nside, i, cb) {
var u = PI_4 * (2 - i / nside);
var t = PI_4 * (1 + (1 - i % 2) / nside);
var begin = tu2fxy(nside, t, u);
var s = begin;
do {
cb(fxy2nest(nside, s.f, s.x, s.y));
s = right_next_pixel(nside, s);
} while (!fxy_compare(s, begin));
}
function fxy_compare(a, b) {
return a.x == b.x && a.y == b.y && a.f == b.f;
}
function right_next_pixel(nside, _a) {
var f = _a.f, x = _a.x, y = _a.y;
++x;
if (x == nside) {
switch (Math.floor(f / 4)) {
case 0:
f = (f + 1) % 4;
x = y;
y = nside;
break;
case 1:
f = f - 4;
x = 0;
break;
case 2:
f = 4 + (f + 1) % 4;
x = 0;
break;
}
}
--y;
if (y == -1) {
switch (Math.floor(f / 4)) {
case 0:
f = 4 + (f + 1) % 4;
y = nside - 1;
break;
case 1:
f = f + 4;
y = nside - 1;
break;
case 2: {
f = 8 + (f + 1) % 4;
y = x - 1;
x = 0;
break;
}
}
}
return { f: f, x: x, y: y };
}
function corners_nest(nside, ipix) {
var _a = nest2fxy(nside, ipix), f = _a.f, x = _a.x, y = _a.y;
var _b = fxy2tu(nside, f, x, y), t = _b.t, u = _b.u;
var d = PI_4 / nside;
var xyzs = [];
for (var _i = 0, _c = [
[0, d],
[-d, 0],
[0, -d],
[d, 0],
]; _i < _c.length; _i++) {
var _d = _c[_i], tt = _d[0], uu = _d[1];
var _e = tu2za(t + tt, u + uu), z = _e.z, a = _e.a;
xyzs.push(za2vec(z, a));
}
return xyzs;
}
exports.corners_nest = corners_nest;
function corners_ring(nside, ipix) {
return corners_nest(nside, ring2nest(nside, ipix));
}
exports.corners_ring = corners_ring;
// pixel area
function nside2pixarea(nside) {
return PI / (3 * nside * nside);
}
exports.nside2pixarea = nside2pixarea;
// average pixel size
function nside2resol(nside) {
return Math.sqrt(PI / 3) / nside;
}
exports.nside2resol = nside2resol;
function pixcoord2vec_nest(nside, ipix, ne, nw) {
var _a = nest2fxy(nside, ipix), f = _a.f, x = _a.x, y = _a.y;
var _b = fxy2tu(nside, f, x, y), t = _b.t, u = _b.u;
var d = PI_4 / nside;
var _c = tu2za(t + d * (ne - nw), u + d * (ne + nw - 1)), z = _c.z, a = _c.a;
return za2vec(z, a);
}
exports.pixcoord2vec_nest = pixcoord2vec_nest;
function pixcoord2vec_ring(nside, ipix, ne, nw) {
return pixcoord2vec_nest(nside, ring2nest(nside, ipix), ne, nw);
}
exports.pixcoord2vec_ring = pixcoord2vec_ring;
function za2pix_nest(nside, z, a) {
var _a = za2tu(z, a), t = _a.t, u = _a.u;
var _b = tu2fxy(nside, t, u), f = _b.f, x = _b.x, y = _b.y;
return fxy2nest(nside, f, x, y);
}
function tu2fxy(nside, t, u) {
var _a = tu2fpq(t, u), f = _a.f, p = _a.p, q = _a.q;
var x = clip(Math.floor(nside * p), 0, nside - 1);
var y = clip(Math.floor(nside * q), 0, nside - 1);
return { f: f, x: x, y: y };
}
exports.tu2fxy = tu2fxy;
function wrap(A, B) {
return A < 0 ? B - (-A % B) : A % B;
}
var PI2 = 2 * Math.PI;
var PI = Math.PI;
var PI_2 = Math.PI / 2;
var PI_4 = Math.PI / 4;
var PI_8 = Math.PI / 8;
function sigma(z) {
if (z < 0)
return -sigma(-z);
else
return 2 - Math.sqrt(3 * (1 - z));
}
/**
* HEALPix spherical projection.
*/
function za2tu(z, a) {
if (Math.abs(z) <= 2. / 3.) { // equatorial belt
var t = a;
var u = 3 * PI_8 * z;
return { t: t, u: u };
}
else { // polar caps
var p_t = a % (PI_2);
var sigma_z = sigma(z);
var t = a - (Math.abs(sigma_z) - 1) * (p_t - PI_4);
var u = PI_4 * sigma_z;
return { t: t, u: u };
}
}
exports.za2tu = za2tu;
/**
* Inverse HEALPix spherical projection.
*/
function tu2za(t, u) {
var abs_u = Math.abs(u);
if (abs_u >= PI_2) { // error
return { z: sign(u), a: 0 };
}
if (abs_u <= Math.PI / 4) { // equatorial belt
var z = 8 / (3 * PI) * u;
var a = t;
return { z: z, a: a };
}
else { // polar caps
var t_t = t % (Math.PI / 2);
var a = t - (abs_u - PI_4) / (abs_u - PI_2) * (t_t - PI_4);
var z = sign(u) * (1 - 1 / 3 * square(2 - 4 * abs_u / PI));
return { z: z, a: a };
}
}
exports.tu2za = tu2za;
// (x, y, z) -> (z = cos(theta), phi)
function vec2za(X, Y, z) {
var r2 = X * X + Y * Y;
if (r2 == 0)
return { z: z < 0 ? -1 : 1, a: 0 };
else {
var a = (Math.atan2(Y, X) + PI2) % PI2;
z /= Math.sqrt(z * z + r2);
return { z: z, a: a };
}
}
// (z = cos(theta), phi) -> (x, y, z)
function za2vec(z, a) {
var sin_theta = Math.sqrt(1 - z * z);
var X = sin_theta * Math.cos(a);
var Y = sin_theta * Math.sin(a);
return [X, Y, z];
}
function ang2vec(theta, phi) {
var z = Math.cos(theta);
return za2vec(z, phi);
}
exports.ang2vec = ang2vec;
function vec2ang(v) {
var _a = vec2za(v[0], v[1], v[2]), z = _a.z, a = _a.a;
return { theta: Math.acos(z), phi: a };
}
exports.vec2ang = vec2ang;
// spherical projection -> f, p, q
// f: base pixel index
// p: coord in north east axis of base pixel
// q: coord in north west axis of base pixel
function tu2fpq(t, u) {
t /= PI_4;
u /= PI_4;
t = wrap(t, 8);
t += -4;
u += 5;
var pp = clip((u + t) / 2, 0, 5);
var PP = Math.floor(pp);
var qq = clip((u - t) / 2, 3 - PP, 6 - PP);
var QQ = Math.floor(qq);
var V = 5 - (PP + QQ);
if (V < 0) { // clip
return { f: 0, p: 1, q: 1 };
}
var H = PP - QQ + 4;
var f = 4 * V + (H >> 1) % 4;
var p = pp % 1;
var q = qq % 1;
return { f: f, p: p, q: q };
}
// f, p, q -> nest index
function fxy2nest(nside, f, x, y) {
return f * nside * nside + bit_combine(x, y);
}
exports.fxy2nest = fxy2nest;
// x = (...x2 x1 x0)_2 <- in binary
// y = (...y2 y1 y0)_2
// p = (...y2 x2 y1 x1 y0 x0)_2
// returns p
function bit_combine(x, y) {
assert(x < (1 << 16));
assert(y < (1 << 15));
return (
// (python)
// n = 14
// ' | '.join(['x & 1'] + [f'(x & 0x{2 ** (i+1):x} | y & 0x{2 ** i:x}) << {i + 1}' for i in range(n)] + [f'y & 0x{2**n:x} << {n+1}'])
x & 1 | (x & 0x2 | y & 0x1) << 1 | (x & 0x4 | y & 0x2) << 2 |
(x & 0x8 | y & 0x4) << 3 | (x & 0x10 | y & 0x8) << 4 | (x & 0x20 | y & 0x10) << 5 |
(x & 0x40 | y & 0x20) << 6 | (x & 0x80 | y & 0x40) << 7 | (x & 0x100 | y & 0x80) << 8 |
(x & 0x200 | y & 0x100) << 9 | (x & 0x400 | y & 0x200) << 10 | (x & 0x800 | y & 0x400) << 11 |
(x & 0x1000 | y & 0x800) << 12 | (x & 0x2000 | y & 0x1000) << 13 | (x & 0x4000 | y & 0x2000) << 14 |
(x & 0x8000 | y & 0x4000) << 15 | y & 0x8000 << 16);
}
exports.bit_combine = bit_combine;
// x = (...x2 x1 x0)_2 <- in binary
// y = (...y2 y1 y0)_2
// p = (...y2 x2 y1 x1 y0 x0)_2
// returns x, y
function bit_decombine(p) {
assert(p <= 0x7fffffff);
// (python)
// ' | '.join(f'(p & 0x{2**(2*i):x}) >> {i}' for i in range(16))
var x = (p & 0x1) >> 0 | (p & 0x4) >> 1 | (p & 0x10) >> 2 |
(p & 0x40) >> 3 | (p & 0x100) >> 4 | (p & 0x400) >> 5 |
(p & 0x1000) >> 6 | (p & 0x4000) >> 7 | (p & 0x10000) >> 8 |
(p & 0x40000) >> 9 | (p & 0x100000) >> 10 | (p & 0x400000) >> 11 |
(p & 0x1000000) >> 12 | (p & 0x4000000) >> 13 | (p & 0x10000000) >> 14 | (p & 0x40000000) >> 15;
// (python)
// ' | '.join(f'(p & 0x{2**(2*i + 1):x}) >> {i+1}' for i in range(15))
var y = (p & 0x2) >> 1 | (p & 0x8) >> 2 | (p & 0x20) >> 3 |
(p & 0x80) >> 4 | (p & 0x200) >> 5 | (p & 0x800) >> 6 |
(p & 0x2000) >> 7 | (p & 0x8000) >> 8 | (p & 0x20000) >> 9 |
(p & 0x80000) >> 10 | (p & 0x200000) >> 11 | (p & 0x800000) >> 12 |
(p & 0x2000000) >> 13 | (p & 0x8000000) >> 14 | (p & 0x20000000) >> 15;
return { x: x, y: y };
}
exports.bit_decombine = bit_decombine;
// f: base pixel index
// x: north east index in base pixel
// y: north west index in base pixel
function nest2fxy(nside, ipix) {
var nside2 = nside * nside;
var f = Math.floor(ipix / nside2); // base pixel index
var k = ipix % nside2; // nested pixel index in base pixel
var _a = bit_decombine(k), x = _a.x, y = _a.y;
return { f: f, x: x, y: y };
}
function fxy2ring(nside, f, x, y) {
var f_row = Math.floor(f / 4); // {0 .. 2}
var f1 = f_row + 2; // {2 .. 4}
var v = x + y;
var i = f1 * nside - v - 1;
if (i < nside) { // north polar cap
var f_col = f % 4;
var ipix = 2 * i * (i - 1) + (i * f_col) + nside - y - 1;
return ipix;
}
if (i < 3 * nside) { // equatorial belt
var h = x - y;
var f2 = 2 * (f % 4) - (f_row % 2) + 1; // {0 .. 7}
var k = (f2 * nside + h + (8 * nside)) % (8 * nside);
var offset = 2 * nside * (nside - 1);
var ipix = offset + (i - nside) * 4 * nside + (k >> 1);
return ipix;
}
else { // south polar cap
var i_i = 4 * nside - i;
var i_f_col = 3 - (f % 4);
var j = 4 * i_i - (i_i * i_f_col) - y;
var i_j = 4 * i_i - j + 1;
var ipix = 12 * nside * nside - 2 * i_i * (i_i - 1) - i_j;
return ipix;
}
}
// f, x, y -> spherical projection
function fxy2tu(nside, f, x, y) {
var f_row = Math.floor(f / 4);
var f1 = f_row + 2;
var f2 = 2 * (f % 4) - (f_row % 2) + 1;
var v = x + y;
var h = x - y;
var i = f1 * nside - v - 1;
var k = (f2 * nside + h + (8 * nside));
var t = k / nside * PI_4;
var u = PI_2 - i / nside * PI_4;
return { t: t, u: u };
}
exports.fxy2tu = fxy2tu;
function orderpix2uniq(order, ipix) {
/**
* Pack `(order, ipix)` into a `uniq` integer.
*
* This HEALPix "unique identifier scheme" is starting to be used widely:
* - see section 3.2 in http://healpix.sourceforge.net/pdf/intro.pdf
* - see section 2.3.1 in http://ivoa.net/documents/MOC/
*/
return 4 * ((1 << (2 * order)) - 1) + ipix;
}
exports.orderpix2uniq = orderpix2uniq;
function uniq2orderpix(uniq) {
/**
* Unpack `uniq` integer into `(order, ipix)`.
*
* Inverse of `orderpix2uniq`.
*/
assert(uniq <= 0x7fffffff);
var order = 0;
var l = (uniq >> 2) + 1;
while (l >= 4) {
l >>= 2;
++order;
}
var ipix = uniq - (((1 << (2 * order)) - 1) << 2);
return { order: order, ipix: ipix };
}
exports.uniq2orderpix = uniq2orderpix;
function ilog2(x) {
/**
* log2 for integer numbers.
*
* We're not calling Math.log2 because it's not supported on IE yet.
*/
var o = -1;
while (x > 0) {
x >>= 1;
++o;
}
return o;
}
var sign = Math.sign || function (A) {
return A > 0 ? 1 : (A < 0 ? -1 : 0);
};
function square(A) {
return A * A;
}
function clip(Z, A, B) {
return Z < A ? A : (Z > B ? B : Z);
}
function assert(condition) {
console.assert(condition);
if (!condition) {
debugger;
}
}