This might somehow more stable
Former-commit-id: bc836c111d6a0bd14aa539c7d35e8987ff96d3da
This commit is contained in:
parent
b939b1c177
commit
22d9f05ef8
|
@ -1,36 +1,33 @@
|
|||
#include "pointgroups.h"
|
||||
#include <search.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
double qpms_pg_quat_cmp_atol = QPMS_QUAT_ATOL;
|
||||
|
||||
#define PAIRCMP(a, b) {\
|
||||
if ((a) < (b)) return -1;\
|
||||
if ((a) > (b)) return 1;\
|
||||
}
|
||||
|
||||
// THIS IS NUMERICALLY UNSTABLE! FIXME!!!!!!
|
||||
int qpms_pg_irot3_cmp(const qpms_irot3_t *p1, const qpms_irot3_t *p2) {
|
||||
QPMS_WARN("NUMERICALLY UNSTABLE! DON'T USE ME!")
|
||||
#define PAIRCMP_ATOL(a, b, atol) {\
|
||||
if ((a) < (b) + (atol)) return -1;\
|
||||
if ((a) + (atol) > (b)) return 1;\
|
||||
}
|
||||
|
||||
int qpms_pg_irot3_approx_cmp(const qpms_irot3_t *p1,
|
||||
const qpms_irot3_t *p2, double atol) {
|
||||
assert(atol >= 0);
|
||||
PAIRCMP(p1->det, p2->det);
|
||||
const qpms_quat_t r1 = qpms_quat_standardise(p1->rot), r2 = qpms_quat_standardise(p2->rot);
|
||||
PAIRCMP(creal(r1.a), creal(r2.a));
|
||||
PAIRCMP(cimag(r1.a), cimag(r2.a));
|
||||
PAIRCMP(creal(r1.b), creal(r2.b));
|
||||
PAIRCMP(cimag(r1.b), cimag(r2.b));
|
||||
const qpms_quat_t r1 = qpms_quat_standardise(p1->rot, atol),
|
||||
r2 = qpms_quat_standardise(p2->rot, atol);
|
||||
PAIRCMP_ATOL(creal(r1.a), creal(r2.a), atol);
|
||||
PAIRCMP_ATOL(cimag(r1.a), cimag(r2.a), atol);
|
||||
PAIRCMP_ATOL(creal(r1.b), creal(r2.b), atol);
|
||||
PAIRCMP_ATOL(cimag(r1.b), cimag(r2.b), atol);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qpms_pg_irot3_cmp_v(const void *av, const void *bv) {
|
||||
const qpms_irot3_t *a = av, *b = bv;
|
||||
return qpms_pg_irot3_cmp(a, b);
|
||||
}
|
||||
|
||||
int qpms_pg_irot3_approx_cmp(const qpms_irot3_t *a, const qpms_irot3_t *b, double atol) {
|
||||
if (qpms_irot3_isclose(*a, *b, atol)) return 0;
|
||||
else return qpms_pg_irot3_cmp(a, b);
|
||||
}
|
||||
|
||||
double qpms_pg_quat_cmp_atol = QPMS_QUAT_ATOL;
|
||||
|
||||
int qpms_pg_irot3_approx_cmp_v(const void *av, const void *bv) {
|
||||
const qpms_irot3_t *a = av, *b = bv;
|
||||
return qpms_pg_irot3_approx_cmp(a, b, qpms_pg_quat_cmp_atol);
|
||||
|
@ -113,7 +110,7 @@ _Bool qpms_pg_is_subgroup(qpms_pointgroup_t small, qpms_pointgroup_t big) {
|
|||
|
||||
qpms_irot3_t *elems_small = qpms_pg_elems(NULL, small);
|
||||
qpms_irot3_t *elems_big = qpms_pg_elems(NULL, small);
|
||||
qsort(elems_big, order_big, sizeof(qpms_irot3_t), qpms_pg_irot3_cmp_v);
|
||||
qsort(elems_big, order_big, sizeof(qpms_irot3_t), qpms_pg_irot3_approx_cmp_v);
|
||||
|
||||
for(qpms_gmi_t smalli = 0; smalli < order_small; ++smalli) {
|
||||
qpms_irot3_t *match = bsearch(&elems_small[smalli], elems_big, order_big,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/*! \file pointgroups.h
|
||||
* \brief Quaternion-represented 3D point groups.
|
||||
*/
|
||||
|
||||
#ifndef POINTGROUPS_H
|
||||
#define POINTGROUPS_H
|
||||
|
||||
|
@ -34,10 +33,6 @@ static inline _Bool qpms_pg_is_finite_axial(qpms_pointgroup_class cls) {
|
|||
*/
|
||||
extern double qpms_pg_quat_cmp_atol;
|
||||
|
||||
/// An ordering of qpms_irot3_t.
|
||||
int qpms_pg_irot3_cmp(const qpms_irot3_t *, const qpms_irot3_t *);
|
||||
/// A `search.h` and `qsort()` compatible ordering of qpms_irot3_t.
|
||||
int qpms_pg_irot3_cmp_v(const void *, const void *);
|
||||
/// An ordering of qpms_irot3_t that considers close enough elements equal.
|
||||
int qpms_pg_irot3_approx_cmp(const qpms_irot3_t *, const qpms_irot3_t *,
|
||||
double atol ///< Absolute tolerance for the quaternion part difference.
|
||||
|
|
|
@ -99,16 +99,15 @@ static inline bool qpms_quat_isclose(const qpms_quat_t p, const qpms_quat_t q, d
|
|||
|
||||
/// "Standardises" a quaternion to have the largest component "positive".
|
||||
/**
|
||||
* FIXME
|
||||
* NUMERICALLY UNSTABLE. DON'T USE
|
||||
* This is to remove the ambiguity stemming from the double cover of SO(3).
|
||||
*/
|
||||
static inline qpms_quat_t qpms_quat_standardise(qpms_quat_t p) {
|
||||
static inline qpms_quat_t qpms_quat_standardise(qpms_quat_t p, double atol) {
|
||||
//assert(atol >= 0);
|
||||
double maxabs = 0;
|
||||
int maxi = 0;
|
||||
const double *arr = (double *) &(p.a);
|
||||
for(int i = 0; i < 4; ++i)
|
||||
if (fabs(arr[i]) > maxabs) {
|
||||
if (fabs(arr[i]) > maxabs + atol) {
|
||||
maxi = i;
|
||||
maxabs = fabs(arr[i]);
|
||||
}
|
||||
|
@ -122,8 +121,8 @@ static inline qpms_quat_t qpms_quat_standardise(qpms_quat_t p) {
|
|||
/// Test approximate equality of "standardised" quaternions, so that \f$-q\f$ is considered equal to \f$q\f$.
|
||||
static inline bool qpms_quat_isclose2(const qpms_quat_t p, const qpms_quat_t q, double atol) {
|
||||
return qpms_quat_norm(qpms_quat_sub(
|
||||
qpms_quat_standardise(p),
|
||||
qpms_quat_standardise(q))) <= atol;
|
||||
qpms_quat_standardise(p, atol),
|
||||
qpms_quat_standardise(q, atol))) <= atol;
|
||||
}
|
||||
|
||||
/// Norm of the quaternion imaginary (vector) part.
|
||||
|
|
Loading…
Reference in New Issue