// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include #include "HKLKey.h" #include "gemmi/symmetry.hpp" uint64_t HKLKey::pack() const { constexpr int bits = 21; constexpr int bias = 1 << (bits - 1); // 1,048,576 constexpr int max_value = bias - 1; constexpr int min_value = -bias; constexpr std::uint64_t mask = (1ULL << bits) - 1ULL; if (h < min_value || h > max_value || k < min_value || k > max_value || l < min_value || l > max_value) { throw std::out_of_range("HKL index outside packable range"); } const std::uint64_t hh = static_cast(h + bias) & mask; const std::uint64_t kk = static_cast(k + bias) & mask; const std::uint64_t ll = static_cast(l + bias) & mask; return (hh << 1) | (kk << (bits + 1)) | (ll << (2 * bits + 1)) | (plus ? 1ULL : 0ULL); } HKLKeyGenerator::HKLKeyGenerator(bool merge_friedel, int32_t space_group_number) : HKLKeyGenerator(merge_friedel, *gemmi::find_spacegroup_by_number(space_group_number)) { } HKLKeyGenerator::HKLKeyGenerator(bool merge_friedel, const gemmi::SpaceGroup &sg) : merge_friedel(merge_friedel), sg(sg), ops(sg.operations()), asu(&sg) { } HKLKey HKLKeyGenerator::operator()(const MergedReflection &r) const { return operator()(r.h, r.k, r.l); } HKLKey HKLKeyGenerator::operator()(const Reflection &r) const { return operator()(r.h, r.k, r.l); } HKLKey HKLKeyGenerator::operator()(int32_t h, int32_t k, int32_t l) const { HKLKey key{h, k, l, true}; if (sg.number == 1) { const HKLKey neg{-h, -k, -l, true}; if (std::tie(key.h, key.k, key.l) < std::tie(neg.h, neg.k, neg.l)) { key.h = -key.h; key.k = -key.k; key.l = -key.l; key.plus = merge_friedel; } } else { const gemmi::Op::Miller in{h, k, l}; const auto [hkl, sign_plus] = asu.to_asu_sign(in, ops); key.h = hkl[0]; key.k = hkl[1]; key.l = hkl[2]; key.plus = merge_friedel ? true : sign_plus; } return key; } bool HKLKeyGenerator::IsSystematicallyAbsent(int32_t h, int32_t k, int32_t l) const { return ops.is_systematically_absent(gemmi::Op::Miller{h, k, l}); } bool HKLKeyGenerator::IsSystematicallyAbsent(const Reflection &r) const { return IsSystematicallyAbsent(r.h, r.k, r.l); } bool AcceptReflection(const Reflection &r, std::optional d_min_limit) { if (!std::isfinite(r.I)) return false; if (!std::isfinite(r.d) || r.d <= 0.0f) return false; if (d_min_limit && r.d < d_min_limit) return false; if (!std::isfinite(r.rlp) || r.rlp == 0.0f) return false; if (!std::isfinite(r.sigma) || r.sigma <= 0.0) return false; return true; } bool AcceptReflection(const Reflection &r, double d_min_limit) { if (!std::isfinite(r.I)) return false; if (!std::isfinite(r.d) || r.d <= 0.0f) return false; if (d_min_limit > 0.0 && r.d < d_min_limit) return false; if (!std::isfinite(r.rlp) || r.rlp == 0.0f) return false; if (!std::isfinite(r.sigma) || r.sigma <= 0.0) return false; return true; }