30#ifndef LSST_SPHGEOM_Q3CPIXELIZATIONIMPL_H_
31#define LSST_SPHGEOM_Q3CPIXELIZATIONIMPL_H_
38#if defined(NO_SIMD) || !defined(__x86_64__)
41 #include <x86intrin.h>
53double const ST_MAX[31] = {
89double const GRID_SCALE[31] = {
125double const FACE_SCALE[31] = {
149 2.384185791015625e-7,
150 1.1920928955078125e-7,
151 5.9604644775390625e-8,
152 2.98023223876953125e-8,
153 1.490116119384765625e-8,
154 7.450580596923828125e-9,
155 3.7252902984619140625e-9,
156 1.86264514923095703125e-9,
231#if defined(NO_SIMD) || !defined(__x86_64__)
233 int faceNumber(UnitVector3d
const & v, uint8_t
const (&faceNumbers)[64]) {
234 int index = ((v.x() > v.y()) << 5) +
235 ((v.x() > -v.y()) << 4) +
236 ((v.x() > v.z()) << 3) +
237 ((v.x() > -v.z()) << 2) +
238 ((v.y() > v.z()) << 1) +
240 return faceNumbers[index];
243 UnitVector3d faceToSphere(
int face,
246 uint8_t
const (&faceComponents)[6][4],
247 double const (&faceConstants)[6][4])
250 double d = u * u + v * v;
252 p[faceComponents[face][0]] = (u * faceConstants[face][0]) / n;
253 p[faceComponents[face][1]] = (v * faceConstants[face][1]) / n;
254 p[faceComponents[face][2]] = faceConstants[face][2] / n;
259 double const gridScale = GRID_SCALE[level];
260 double const stMax = ST_MAX[level];
261 double s = u * gridScale + gridScale;
262 double t = v * gridScale + gridScale;
266 static_cast<int32_t
>(t));
270 double const faceScale = FACE_SCALE[level];
272 static_cast<double>(t) * faceScale - 1.0);
277 u * (1.3333333333333333 - 0.3333333333333333 *
std::fabs(u)),
278 v * (1.3333333333333333 - 0.3333333333333333 *
std::fabs(v))
291 int faceNumber(UnitVector3d
const & v, uint8_t
const (&faceNumbers)[64]) {
292 __m128d
const m00 = _mm_set_pd(0.0, -0.0);
293 __m128d xx = _mm_set1_pd(v.x());
294 __m128d yy = _mm_set1_pd(v.y());
295 __m128d zz = _mm_set1_pd(v.z());
296 __m128d myy = _mm_xor_pd(yy, m00);
297 __m128d mzz = _mm_xor_pd(zz, m00);
298 int index = (_mm_movemask_pd(_mm_cmpgt_pd(xx, myy)) << 4) +
299 (_mm_movemask_pd(_mm_cmpgt_pd(xx, mzz)) << 2) +
300 _mm_movemask_pd(_mm_cmpgt_pd(yy, mzz));
301 return faceNumbers[index];
304 UnitVector3d faceToSphere(
int face,
306 uint8_t
const (&faceComponents)[6][4],
307 double const (&faceConstants)[6][4])
310 __m128d norm = _mm_mul_pd(uv, uv);
315 _mm_add_sd(norm, _mm_unpackhi_pd(norm, _mm_setzero_pd()))
318 __m128d
w = _mm_set_sd(faceConstants[face][2]);
319 w = _mm_div_sd(
w, norm);
321 _mm_div_pd(uv, _mm_shuffle_pd(norm, norm, 0)),
322 _mm_load_pd(&faceConstants[face][0])
324 _mm_store_sd(&p[faceComponents[face][0]], uv);
325 _mm_storeh_pd(&p[faceComponents[face][1]], uv);
326 _mm_store_sd(&p[faceComponents[face][2]],
w);
330 __m128i faceToGrid(
int level, __m128d uv) {
331 __m128d
const gridScale = _mm_set1_pd(GRID_SCALE[level]);
332 __m128d
const stMax = _mm_set1_pd(ST_MAX[level]);
333 __m128d st = _mm_add_pd(_mm_mul_pd(uv, gridScale), gridScale);
334 st = _mm_min_pd(_mm_max_pd(st, _mm_setzero_pd()), stMax);
335 return _mm_shuffle_epi32(_mm_cvttpd_epi32(st), 0x98);
338 __m128d gridToFace(
int level, __m128i st) {
339 __m128d
const faceScale = _mm_set1_pd(FACE_SCALE[level]);
340 __m128d xy = _mm_cvtepi32_pd(_mm_shuffle_epi32(st, 8));
341 return _mm_sub_pd(_mm_mul_pd(xy, faceScale), _mm_set1_pd(1.0));
344 __m128d atanApprox(__m128d uv) {
345 __m128d abs_uv = _mm_andnot_pd(_mm_set_pd(-0.0, -0.0), uv);
349 _mm_set1_pd(1.3333333333333333),
350 _mm_mul_pd(_mm_set1_pd(0.3333333333333333), abs_uv)
355 __m128d atanApproxInverse(__m128d uv) {
356 __m128d signbits = _mm_and_pd(uv, _mm_set_pd(-0.0, -0.0));
357 __m128d abs_uv = _mm_andnot_pd(_mm_set_pd(-0.0, -0.0), uv);
358 __m128d tmp = _mm_sub_pd(_mm_set1_pd(4.0),
359 _mm_mul_pd(_mm_set1_pd(3.0), abs_uv));
360 uv = _mm_sub_pd(_mm_set1_pd(2.0), _mm_sqrt_pd(tmp));
361 return _mm_or_pd(signbits, uv);
This file declares a class for representing unit vectors in ℝ³.
static UnitVector3d fromNormalized(Vector3d const &v)
fromNormalized returns the unit vector equal to v, which is assumed to be normalized.