1#ifndef SEAMS_SIMD_DISTANCE_H_
2#define SEAMS_SIMD_DISTANCE_H_
7#if defined(__has_include)
8#if __has_include(<span>)
10#define SEAMS_HAS_STD_SPAN 1
14#ifdef SEAMS_HAS_MINIMAGE
20#include "hwy/highway.h"
24namespace hn = hwy::HWY_NAMESPACE;
35 const double* HWY_RESTRICT dy,
36 const double* HWY_RESTRICT dz,
37 double bx,
double by,
double bz,
38 double* HWY_RESTRICT out,
size_t n) {
39#ifdef SEAMS_HAS_MINIMAGE
40 if (mi_dist2_ortho_diffs(dx, dy, dz, bx, by, bz, out, n) == 0) {
44 const hn::ScalableTag<double> d;
45 const size_t N = hn::Lanes(d);
47 const auto vbx = hn::Set(d, bx);
48 const auto vby = hn::Set(d, by);
49 const auto vbz = hn::Set(d, bz);
54 const double rbx = 1.0 / bx;
55 const double rby = 1.0 / by;
56 const double rbz = 1.0 / bz;
57 const auto vrbx = hn::Set(d, rbx);
58 const auto vrby = hn::Set(d, rby);
59 const auto vrbz = hn::Set(d, rbz);
62 for (; i + N <= n; i += N) {
65 auto vdx = hn::LoadU(d, dx + i);
66 auto vdy = hn::LoadU(d, dy + i);
67 auto vdz = hn::LoadU(d, dz + i);
75 vdx = hn::NegMulAdd(vbx, hn::Round(hn::Mul(vdx, vrbx)), vdx);
76 vdy = hn::NegMulAdd(vby, hn::Round(hn::Mul(vdy, vrby)), vdy);
77 vdz = hn::NegMulAdd(vbz, hn::Round(hn::Mul(vdz, vrbz)), vdz);
80 auto r2 = hn::MulAdd(vdx, vdx, hn::MulAdd(vdy, vdy, hn::Mul(vdz, vdz)));
81 hn::StoreU(r2, d, out + i);
86 double ddx = std::fabs(dx[i]);
87 double ddy = std::fabs(dy[i]);
88 double ddz = std::fabs(dz[i]);
89 ddx -= bx * std::round(ddx * rbx);
90 ddy -= by * std::round(ddy * rby);
91 ddz -= bz * std::round(ddz * rbz);
92 out[i] = ddx * ddx + ddy * ddy + ddz * ddz;
103 const double* dz,
double bx,
double by,
104 double bz,
double* out,
size_t n) {
105#ifdef SEAMS_HAS_MINIMAGE
106 if (mi_dist2_ortho_diffs(dx, dy, dz, bx, by, bz, out, n) == 0) {
111 const double rbx = 1.0 / bx;
112 const double rby = 1.0 / by;
113 const double rbz = 1.0 / bz;
114 for (
size_t i = 0; i < n; i++) {
115 double ddx = std::fabs(dx[i]);
116 double ddy = std::fabs(dy[i]);
117 double ddz = std::fabs(dz[i]);
118 ddx -= bx * std::round(ddx * rbx);
119 ddy -= by * std::round(ddy * rby);
120 ddz -= bz * std::round(ddz * rbz);
121 out[i] = ddx * ddx + ddy * ddy + ddz * ddz;
140#ifdef SEAMS_HAS_STD_SPAN
142 std::span<const double> dy,
143 std::span<const double> dz,
double bx,
144 double by,
double bz, std::span<double> out) {
145 const size_t n = std::min({dx.size(), dy.size(), dz.size(), out.size()});
void BatchPeriodicDistSq(const double *dx, const double *dy, const double *dz, double bx, double by, double bz, double *out, size_t n)