27 #include "cif++/point.hpp" 43 uint32_t
dim_m()
const {
return static_cast<const M &
>(*this).dim_m(); }
44 uint32_t
dim_n()
const {
return static_cast<const M &
>(*this).dim_n(); }
48 return static_cast<M &
>(*this).operator()(
i,
j);
53 return static_cast<const M &
>(*this).operator()(
i,
j);
64 template <
typename M2>
70 for (uint32_t
i = 0;
i < m_m; ++
i)
72 for (uint32_t
j = 0;
j < m_n; ++
j)
73 operator()(
i,
j) =
m(
i,
j);
82 std::fill(m_data.begin(), m_data.end(), v);
91 size_t dim_m()
const {
return m_m; }
92 size_t dim_n()
const {
return m_n; }
98 return m_data[i * m_n +
j];
105 return m_data[i * m_n +
j];
109 size_t m_m = 0, m_n = 0;
110 std::vector<double> m_data;
120 , m_data((m_n * (m_n + 1)) / 2)
122 std::fill(m_data.begin(), m_data.end(), v);
131 uint32_t
dim_m()
const {
return m_n; }
132 uint32_t
dim_n()
const {
return m_n; }
137 ? m_data[(j * (j + 1)) / 2 +
i]
138 : m_data[(i * (i + 1)) / 2 +
j];
146 return m_data[(j * (j + 1)) / 2 +
i];
151 std::vector<double> m_data;
162 uint32_t
dim_m()
const {
return m_n; }
163 uint32_t
dim_n()
const {
return m_n; }
167 return i == j ? 1 : 0;
177 template <
typename M1,
typename M2>
185 assert(m_m1.dim_m() == m_m2.dim_m());
186 assert(m_m1.dim_n() == m_m2.dim_n());
189 uint32_t
dim_m()
const {
return m_m1.dim_m(); }
190 uint32_t
dim_n()
const {
return m_m1.dim_n(); }
194 return m_m1(i, j) - m_m2(i, j);
202 template <
typename M1,
typename M2>
205 return MatrixSubtraction(*static_cast<const M1 *>(&m1), *static_cast<const M2 *>(&m2));
208 template <
typename M>
218 uint32_t
dim_m()
const {
return m_m.dim_m(); }
219 uint32_t
dim_n()
const {
return m_m.dim_n(); }
223 return m_m(i, j) * m_v;
231 template <
typename M>
242 Matrix cf(m.dim_m(), m.dim_m());
244 const size_t ixs[4][3] = {
251 for (
size_t x = 0;
x < 4; ++
x)
253 const size_t *ix = ixs[
x];
255 for (
size_t y = 0;
y < 4; ++
y)
257 const size_t *iy = ixs[
y];
260 m(ix[0], iy[0]) *
m(ix[1], iy[1]) *
m(ix[2], iy[2]) +
261 m(ix[0], iy[1]) *
m(ix[1], iy[2]) *
m(ix[2], iy[0]) +
262 m(ix[0], iy[2]) *
m(ix[1], iy[0]) *
m(ix[2], iy[1]) -
263 m(ix[0], iy[2]) *
m(ix[1], iy[1]) *
m(ix[2], iy[0]) -
264 m(ix[0], iy[1]) *
m(ix[1], iy[0]) *
m(ix[2], iy[2]) -
265 m(ix[0], iy[0]) *
m(ix[1], iy[2]) *
m(ix[2], iy[1]);
267 if ((
x +
y) % 2 == 1)
280 std::valarray<double> t(4);
292 q /=
static_cast<quaternion::value_type
>(
length);
294 q = quaternion(1, 0, 0, 0);
303 auto q = std::cos((angle * kPI / 180) / 2);
309 static_cast<float>(q),
310 static_cast<float>(s * axis.m_x),
311 static_cast<float>(s * axis.m_y),
312 static_cast<float>(s * axis.m_z) });
321 double angle = 2 * std::acos(q.get_a());
322 angle = angle * 180 / kPI;
325 float s =
std::sqrt(1 - q.get_a() * q.get_a());
329 point axis(q.get_b() / s, q.get_c() / s, q.get_d() / s);
331 return { angle,
axis };
338 for (
point &pt : Points)
345 t.m_x /= Points.size();
346 t.m_y /= Points.size();
347 t.m_z /= Points.size();
349 for (
point &pt : Points)
360 float angle,
float esd)
370 float dh = dihedral_angle(p1, p2, p3, p4);
373 float delta = std::fmod(angle - dh, 360.0
f);
391 dh = dihedral_angle(p1, p2, p3, p4);
404 result /=
static_cast<float>(pts.size());
409 double RMSd(
const std::vector<point> &
a,
const std::vector<point> &
b)
412 for (uint32_t
i = 0;
i < a.size(); ++
i)
414 std::valarray<double>
d(3);
416 d[0] = b[
i].m_x - a[
i].m_x;
417 d[1] = b[
i].m_y - a[
i].m_y;
418 d[2] = b[
i].m_z - a[
i].m_z;
439 std::complex<double> P = -(a *
a) / 12 - c;
440 std::complex<double> Q = -(a * a *
a) / 108 + (a * c) / 3 - (b *
b) / 8;
441 std::complex<double> R = -Q / 2.0 +
std::sqrt((Q * Q) / 4.0 + (P * P * P) / 27.0);
443 std::complex<double> U = std::pow(R, 1 / 3.0);
445 std::complex<double>
y;
447 y = -5.0 * a / 6.0 + U - std::pow(Q, 1.0 / 3.0);
449 y = -5.0 * a / 6.0 + U - P / (3.0 * U);
451 std::complex<double> W =
std::sqrt(a + 2.0 * y);
457 std::valarray<double> t(4);
459 t[0] = ((W +
std::sqrt(-(3.0 * a + 2.0 * y + 2.0 * b / W))) / 2.0).real();
460 t[1] = ((W +
std::sqrt(-(3.0 * a + 2.0 * y - 2.0 * b / W))) / 2.0).real();
461 t[2] = ((-W +
std::sqrt(-(3.0 * a + 2.0 * y + 2.0 * b / W))) / 2.0).real();
462 t[3] = ((-W +
std::sqrt(-(3.0 * a + 2.0 * y - 2.0 * b / W))) / 2.0).real();
467 quaternion
align_points(
const std::vector<point> &pa,
const std::vector<point> &pb)
472 for (uint32_t
i = 0;
i < pa.size(); ++
i)
477 M(0, 0) += a.m_x * b.m_x;
478 M(0, 1) += a.m_x * b.m_y;
479 M(0, 2) += a.m_x * b.m_z;
480 M(1, 0) += a.m_y * b.m_x;
481 M(1, 1) += a.m_y * b.m_y;
482 M(1, 2) += a.m_y * b.m_z;
483 M(2, 0) += a.m_z * b.m_x;
484 M(2, 1) += a.m_z * b.m_y;
485 M(2, 2) += a.m_z * b.m_z;
491 N(0, 0) = M(0, 0) + M(1, 1) + M(2, 2);
492 N(0, 1) = M(1, 2) - M(2, 1);
493 N(0, 2) = M(2, 0) - M(0, 2);
494 N(0, 3) = M(0, 1) - M(1, 0);
496 N(1, 1) = M(0, 0) - M(1, 1) - M(2, 2);
497 N(1, 2) = M(0, 1) + M(1, 0);
498 N(1, 3) = M(0, 2) + M(2, 0);
500 N(2, 2) = -M(0, 0) + M(1, 1) - M(2, 2);
501 N(2, 3) = M(1, 2) + M(2, 1);
503 N(3, 3) = -M(0, 0) - M(1, 1) + M(2, 2);
514 double C = -2 * (M(0, 0) * M(0, 0) + M(0, 1) * M(0, 1) + M(0, 2) * M(0, 2) +
515 M(1, 0) * M(1, 0) + M(1, 1) * M(1, 1) + M(1, 2) * M(1, 2) +
516 M(2, 0) * M(2, 0) + M(2, 1) * M(2, 1) + M(2, 2) * M(2, 2));
518 double D = 8 * (M(0, 0) * M(1, 2) * M(2, 1) +
519 M(1, 1) * M(2, 0) * M(0, 2) +
520 M(2, 2) * M(0, 1) * M(1, 0)) -
521 8 * (M(0, 0) * M(1, 1) * M(2, 2) +
522 M(1, 2) * M(2, 0) * M(0, 1) +
523 M(2, 1) * M(1, 0) * M(0, 2));
527 (N(0, 0) * N(1, 1) - N(0, 1) * N(0, 1)) * (N(2, 2) * N(3, 3) - N(2, 3) * N(2, 3)) +
528 (N(0, 1) * N(0, 2) - N(0, 0) * N(2, 1)) * (N(2, 1) * N(3, 3) - N(2, 3) * N(1, 3)) +
529 (N(0, 0) * N(1, 3) - N(0, 1) * N(0, 3)) * (N(2, 1) * N(2, 3) - N(2, 2) * N(1, 3)) +
530 (N(0, 1) * N(2, 1) - N(1, 1) * N(0, 2)) * (N(0, 2) * N(3, 3) - N(2, 3) * N(0, 3)) +
531 (N(1, 1) * N(0, 3) - N(0, 1) * N(1, 3)) * (N(0, 2) * N(2, 3) - N(2, 2) * N(0, 3)) +
532 (N(0, 2) * N(1, 3) - N(2, 1) * N(0, 3)) * (N(0, 2) * N(1, 3) - N(2, 1) * N(0, 3));
544 for (
int r = 1; r < 4; ++r)
551 static_cast<float>(cf(maxR, 0)),
552 static_cast<float>(cf(maxR, 1)),
553 static_cast<float>(cf(maxR, 2)),
554 static_cast<float>(cf(maxR, 3)));
564 static const float kPI_f =
static_cast<float>(kPI);
566 static std::random_device rd;
567 static std::mt19937_64 rng(rd());
569 std::uniform_real_distribution<float> randomAngle(0, 2 * kPI_f);
570 std::normal_distribution<float> randomOffset(0, offset);
572 float theta = randomAngle(rng);
573 float phi1 = randomAngle(rng) - kPI_f;
574 float phi2 = randomAngle(rng) - kPI_f;
576 quaternion q = spherical(1.0
f, theta, phi1, phi2);
580 r *= randomOffset(rng);
Matrix Cofactors(const M1 &m)
double operator()(uint32_t i, uint32_t j) const
quaternion align_points(const std::vector< point > &pa, const std::vector< point > &pb)
n The following was calculated during iteration
point center_points(std::vector< point > &Points)
point centroid(const std::vector< point > &pts)
double & operator()(uint32_t i, uint32_t j)
MatrixSubtraction< M1, M2 > operator-(const MatrixExpression< M1 > &m1, const MatrixExpression< M2 > &m2)
void sqrt(Image< double > &op)
void abs(Image< double > &op)
MatrixSubtraction(const M1 &m1, const M2 &m2)
double operator()(size_t i, size_t j) const
quaternion construct_for_dihedral_angle(point p1, point p2, point p3, point p4, float angle, float esd)
double & operator()(size_t i, size_t j)
double RMSd(const std::vector< point > &a, const std::vector< point > &b)
quaternion_type< T > normalize(quaternion_type< T > q)
__host__ __device__ float length(float2 v)
quaternion construct_from_angle_axis(float angle, point axis)
MatrixMultiplication(const M &m, double v)
double operator()(uint32_t i, uint32_t j) const
double LargestDepressedQuarticSolution(double a, double b, double c)
point nudge(point p, float offset)
double operator()(uint32_t i, uint32_t j) const
IdentityMatrix(uint32_t n)
MatrixMultiplication< M > operator*(const MatrixExpression< M > &m, double v)
std::tuple< double, point > quaternion_to_angle_axis(quaternion q)
Matrix(const MatrixExpression< M2 > &m)
double & operator()(uint32_t i, uint32_t j)
Matrix(size_t m, size_t n, double v=0)
double operator()(uint32_t i, uint32_t j) const
double operator()(uint32_t i, uint32_t j) const
SymmetricMatrix(uint32_t n, double v=0)