aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/CMakeLists.txt4
-rw-r--r--tests/centering_check.c22
-rw-r--r--tests/rational_check.c194
-rw-r--r--tests/transformation_check.c227
4 files changed, 355 insertions, 92 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 02f3ca02..beb141c3 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -83,3 +83,7 @@ if (HAVE_OPENCL)
add_test(gpu_sim_check gpu_sim_check)
endif (HAVE_OPENCL)
+add_executable(rational_check rational_check.c)
+target_include_directories(rational_check PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(rational_check ${COMMON_LIBRARIES})
+add_test(rational_check rational_check)
diff --git a/tests/centering_check.c b/tests/centering_check.c
index 887311dd..cc553dd0 100644
--- a/tests/centering_check.c
+++ b/tests/centering_check.c
@@ -61,7 +61,8 @@ static int check_centering(double a, double b, double c,
{
UnitCell *cell, *cref;
UnitCell *n;
- UnitCellTransformation *t;
+ IntegerMatrix *C;
+ RationalMatrix *Ci;
int fail = 0;
int i;
double asx, asy, asz;
@@ -86,14 +87,19 @@ static int check_centering(double a, double b, double c,
cell_free(cref);
check_cell(cell, "Input");
- n = uncenter_cell(cell, &t);
+ n = uncenter_cell(cell, &C, &Ci);
if ( n != NULL ) {
- STATUS("Transformation was:\n");
- tfn_print(t);
+ STATUS("The back transformation is:\n");
+ intmat_print(C);
if ( check_cell(n, "Output") ) fail = 1;
- if ( !fail ) cell_print(n);
+ if ( intmat_is_identity(C) && ((cen=='P') || (cen=='R')) ) {
+ STATUS("Identity, as expected.\n");
+ } else {
+ cell_print(n);
+ }
} else {
- fail = 1;
+ STATUS("************* Could not uncenter.\n");
+ return 1;
}
cell_get_reciprocal(cell, &asx, &asy, &asz,
@@ -299,10 +305,6 @@ int main(int argc, char *argv[])
fail += check_centering(20e-10, 20e-10, 40e-10, 90.0, 90.0, 120.0,
L_HEXAGONAL, 'H', 'c', rng);
- /* Cubic P */
- fail += check_centering(30e-10, 30e-10, 30e-10, 90.0, 90.0, 90.0,
- L_CUBIC, 'P', '*', rng);
-
/* Cubic I */
fail += check_centering(30e-10, 30e-10, 30e-10, 90.0, 90.0, 90.0,
L_CUBIC, 'I', '*', rng);
diff --git a/tests/rational_check.c b/tests/rational_check.c
new file mode 100644
index 00000000..484264d9
--- /dev/null
+++ b/tests/rational_check.c
@@ -0,0 +1,194 @@
+/*
+ * rational_check.c
+ *
+ * Check that rational numbers work
+ *
+ * Copyright © 2012-2019 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2012-2019 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <gsl/gsl_rng.h>
+
+#include <rational.h>
+#include <utils.h>
+
+
+static Rational gen_rtnl(gsl_rng *rng, double *dptr, int sz)
+{
+ Rational r;
+ signed int num, den;
+ do {
+ num = gsl_rng_uniform_int(rng, 2*sz) - sz;
+ den = gsl_rng_uniform_int(rng, 2*sz) - sz;
+ } while ( den == 0 );
+ r = rtnl(num, den);
+ *dptr = (double)num/den;
+ return r;
+}
+
+
+static int test_rational(gsl_rng *rng)
+{
+ Rational r1, r2, r3;
+ double rd1, rd2, rd3;
+ char op;
+
+ r1 = gen_rtnl(rng, &rd1, 100);
+ r2 = gen_rtnl(rng, &rd2, 100);
+
+ switch ( gsl_rng_uniform_int(rng, 3) ) {
+
+ case 0:
+ r3 = rtnl_mul(r1, r2);
+ rd3 = rd1*rd2;
+ op = '*';
+ break;
+
+ case 1:
+ r3 = rtnl_div(r1, r2);
+ rd3 = rd1/rd2;
+ op = '/';
+ break;
+
+ case 2:
+ r3 = rtnl_add(r1, r2);
+ rd3 = rd1+rd2;
+ op = '+';
+ break;
+
+ case 3:
+ r3 = rtnl_sub(r1, r2);
+ rd3 = rd1-rd2;
+ op = '-';
+ break;
+
+ default:
+ abort();
+
+ }
+
+ if ( isinf(rd3) && isinf(rtnl_as_double(r3)) ) return 0;
+
+ if ( fabs(rtnl_as_double(r3) - rd3) > 0.001 ) {
+ ERROR("%10s %c %10s = %10s", rtnl_format(r1), op,
+ rtnl_format(r2), rtnl_format(r3));
+ ERROR(" ---> %10f %c %10f = %10f\n", rd1, op, rd2, rd3);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int test_rational_matrix(gsl_rng *rng)
+{
+ const int size = 3;
+ RationalMatrix *rm;
+ Rational *rvec;
+ Rational *rans;
+ gsl_matrix *gm;
+ gsl_vector *gvec;
+ gsl_vector *gans;
+ int i, j;
+ int filt;
+ int fail = 0;
+
+ rm = rtnl_mtx_new(size, size);
+ gm = gsl_matrix_alloc(size, size);
+ rvec = malloc(size*sizeof(Rational));
+ gvec = gsl_vector_alloc(size);
+ rans = malloc(size*sizeof(Rational));
+ if ( (rm==NULL) || (gm==NULL) || (rvec==NULL)
+ || (gvec==NULL) || (rans==NULL) ) return 1;
+
+ /* Find a matrix equation which actually works */
+ do {
+ for ( i=0; i<size; i++ ) {
+ double d;
+ Rational r;
+ for ( j=0; j<size; j++ ) {
+ r = gen_rtnl(rng, &d, 5);
+ rtnl_mtx_set(rm, i, j, r);
+ gsl_matrix_set(gm ,i, j, d);
+ }
+ r = gen_rtnl(rng, &d, 5);
+ rvec[i] = r;
+ gsl_vector_set(gvec ,i, d);
+ }
+
+ gans = solve_svd(gvec, gm, &filt, 0);
+ } while ( (gans==NULL) || (filt!=0) || (isnan(gsl_vector_get(gans,0))) );
+
+ transform_fractional_coords_rtnl(rm, rvec, rans);
+
+ for ( i=0; i<size; i++ ) {
+ if ( fabs(rtnl_as_double(rans[i]) - gsl_vector_get(gans, i) > 0.001) )
+ {
+ STATUS("%25s %10f %10f\n", rtnl_format(rans[i]),
+ rtnl_as_double(rans[i]),
+ gsl_vector_get(gans, i));
+ fail = 1;
+ }
+ }
+
+ gsl_matrix_free(gm);
+ rtnl_mtx_free(rm);
+ free(rans);
+ free(rvec);
+ gsl_vector_free(gvec);
+ gsl_vector_free(gans);
+ return fail;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int fail = 0;
+ gsl_rng *rng;
+ int i;
+
+ rng = gsl_rng_alloc(gsl_rng_mt19937);
+ gsl_set_error_handler_off();
+
+ STATUS("Arithmetic test...\n");
+ for ( i=0; i<1000; i++ ) {
+ fail += test_rational(rng);
+ }
+
+ STATUS("Matrix test...\n");
+ for ( i=0; i<1000; i++ ) {
+ fail += test_rational_matrix(rng);
+ }
+
+ gsl_rng_free(rng);
+
+ if ( fail != 0 ) return 1;
+ return 0;
+}
diff --git a/tests/transformation_check.c b/tests/transformation_check.c
index 2e7e7378..2790d6f1 100644
--- a/tests/transformation_check.c
+++ b/tests/transformation_check.c
@@ -37,6 +37,7 @@
#include <cell.h>
#include <cell-utils.h>
+#include <symmetry.h>
#define MAX_REFLS (10*1024)
@@ -134,52 +135,61 @@ static int compare_rvecs(struct rvec *a, int na, struct rvec *b, int nb)
}
-static int check_transformation(UnitCell *cell, UnitCellTransformation *tfn,
- int pred_test, UnitCell *ct)
+static int check_same_reflections(UnitCell *cell, UnitCell *cnew)
{
- UnitCell *cnew, *cback;
- UnitCellTransformation *inv;
- double a[9], b[9];
- int i;
- int fail = 0;
struct rvec *vecs;
struct rvec *tvecs;
int na, nb;
- STATUS("-----------------------\n");
- if ( ct == NULL ) {
- cnew = cell_transform(cell, tfn);
+ /* Check that the two cells predict the same reflections */
+ vecs = all_refls(cell, 1e9, &na);
+ tvecs = all_refls(cnew, 1e9, &nb);
+ if ( compare_rvecs(vecs, na, tvecs, nb)
+ || compare_rvecs(tvecs, nb, vecs, na) )
+ {
+ ERROR("********************************************** ");
+ ERROR("Transformed cell didn't predict the same reflections\n");
+ //printf("---\n");
+ //for ( i=0; i<na; i++ ) {
+ // printf("%e %e %e\n", vecs[i].u, vecs[i].v, vecs[i].w);
+ //}
+ //printf("---\n");
+ //for ( i=0; i<nb; i++ ) {
+ // printf("%e %e %e\n", tvecs[i].u, tvecs[i].v, tvecs[i].w);
+ //}
+ return 1;
} else {
- cnew = ct;
+ STATUS("The cells predict the same reflections.\n");
}
- cback = cell_transform_inverse(cnew, tfn);
+ free(vecs);
+ free(tvecs);
+ return 0;
+}
+
+
+static int check_transformation(UnitCell *cell, IntegerMatrix *tfn,
+ int pred_test)
+{
+ UnitCell *cnew, *cback;
+ double a[9], b[9];
+ int i;
+ int fail = 0;
+
+ STATUS("-----------------------\n");
+ cnew = cell_transform_intmat(cell, tfn);
+ cback = cell_transform_intmat_inverse(cnew, tfn);
+ STATUS("----> Before transformation:\n");
cell_print(cell);
- tfn_print(tfn);
+ STATUS("----> The transformation matrix:\n");
+ intmat_print(tfn);
+ STATUS("----> After transformation:\n");
cell_print(cnew);
+ STATUS("----> After back transformation:\n");
+ cell_print(cback);
if ( pred_test ) {
- /* Check that the two cells predict the same reflections */
- vecs = all_refls(cell, 1e9, &na);
- tvecs = all_refls(cnew, 1e9, &nb);
- if ( compare_rvecs(vecs, na, tvecs, nb)
- || compare_rvecs(tvecs, nb, vecs, na) )
- {
- ERROR("Transformed cell didn't predict the same reflections\n");
- //printf("---\n");
- //for ( i=0; i<na; i++ ) {
- // printf("%e %e %e\n", vecs[i].u, vecs[i].v, vecs[i].w);
- //}
- //printf("---\n");
- //for ( i=0; i<nb; i++ ) {
- // printf("%e %e %e\n", tvecs[i].u, tvecs[i].v, tvecs[i].w);
- //}
- return 1;
- } else {
- STATUS("The cells predict the same reflections.\n");
- }
- free(vecs);
- free(tvecs);
+ check_same_reflections(cell, cnew);
} else {
STATUS("Cells not expected to predict the same reflections.\n");
}
@@ -193,18 +203,18 @@ static int check_transformation(UnitCell *cell, UnitCellTransformation *tfn,
&b[6], &b[7], &b[8]);
for ( i=0; i<9; i++ ) {
if ( !tolerance(a[i], b[i]) ) {
+ //STATUS("%e %e\n", a[i], b[i]);
fail = 1;
- STATUS("%e %e\n", a[i], b[i]);
}
}
if ( fail ) {
+ ERROR("********************************************** ");
ERROR("Original cell not recovered after transformation:\n");
- cell_print(cell);
- tfn_print(tfn);
- inv = tfn_inverse(tfn);
- tfn_print(inv);
+ STATUS("----> After transformation and transformation back:\n");
cell_print(cback);
+ } else {
+ STATUS("The original cell was recovered after inverse transform.\n");
}
return fail;
@@ -214,21 +224,73 @@ static int check_transformation(UnitCell *cell, UnitCellTransformation *tfn,
static int check_uncentering(UnitCell *cell)
{
UnitCell *ct;
- UnitCellTransformation *tr;
+ IntegerMatrix *C;
+ RationalMatrix *Ci;
+ UnitCell *cback;
+ double a[9], b[9];
+ int i;
+ int fail = 0;
+
+ STATUS("-----------------------\n");
+
+ STATUS("----> Before transformation:\n");
+ cell_print_full(cell);
+
+ ct = uncenter_cell(cell, &C, &Ci);
+ if ( ct == NULL ) return 1;
+
+ STATUS("----> The primitive unit cell:\n");
+ cell_print(ct);
- ct = uncenter_cell(cell, &tr);
- return check_transformation(cell, tr, 1, ct);
+ STATUS("----> The matrix to put the centering back:\n");
+ intmat_print(C);
+
+ STATUS("----> The recovered centered cell:\n");
+ cback = cell_transform_intmat(ct, C);
+ cell_print(cback);
+
+ cell_get_cartesian(cell, &a[0], &a[1], &a[2],
+ &a[3], &a[4], &a[5],
+ &a[6], &a[7], &a[8]);
+ cell_get_cartesian(cback, &b[0], &b[1], &b[2],
+ &b[3], &b[4], &b[5],
+ &b[6], &b[7], &b[8]);
+ for ( i=0; i<9; i++ ) {
+ if ( fabs(a[i] - b[i]) > 1e-12 ) {
+ fail = 1;
+ }
+ }
+
+ if ( fail ) {
+ ERROR("********************************************** ");
+ ERROR("Original cell not recovered after back transformation\n");
+ }
+
+ fail += check_same_reflections(cell, ct);
+ cell_free(ct);
+ cell_free(cback);
+
+ return fail;
}
-static int check_identity(UnitCell *cell, UnitCellTransformation *tfn)
+static int check_identity(UnitCell *cell, IntegerMatrix *tfn)
{
UnitCell *cnew;
double a[9], b[9];
int i;
int fail = 0;
- cnew = cell_transform(cell, tfn);
+ STATUS("-----------------------\n");
+
+ cnew = cell_transform_intmat(cell, tfn);
+
+ STATUS("----> Before identity transformation:\n");
+ cell_print(cell);
+ STATUS("----> The identity transformation matrix:\n");
+ intmat_print(tfn);
+ STATUS("----> After identity transformation:\n");
+ cell_print(cnew);
cell_get_cartesian(cell, &a[0], &a[1], &a[2],
&a[3], &a[4], &a[5],
@@ -239,14 +301,15 @@ static int check_identity(UnitCell *cell, UnitCellTransformation *tfn)
for ( i=0; i<9; i++ ) {
if ( !within_tolerance(a[i], b[i], 0.1) ) {
fail = 1;
- STATUS("%e %e\n", a[i], b[i]);
+ //STATUS("%e %e\n", a[i], b[i]);
}
}
if ( fail ) {
- ERROR("Original cell not recovered after transformation:\n");
+ ERROR("********************************************** ");
+ ERROR("Original cell not recovered after identity transformation:\n");
cell_print(cell);
- tfn_print(tfn);
+ intmat_print(tfn);
cell_print(cnew);
}
@@ -258,7 +321,8 @@ int main(int argc, char *argv[])
{
int fail = 0;
UnitCell *cell, *cref;
- UnitCellTransformation *tfn;
+ IntegerMatrix *tfn;
+ IntegerMatrix *part1, *part2;
gsl_rng *rng;
rng = gsl_rng_alloc(gsl_rng_mt19937);
@@ -273,53 +337,52 @@ int main(int argc, char *argv[])
if ( cell == NULL ) return 1;
cell_free(cref);
+ tfn = intmat_identity(3);
+
/* Permutation of axes */
- tfn = tfn_identity();
if ( tfn == NULL ) return 1;
- tfn_combine(tfn, tfn_vector(0,1,0),
- tfn_vector(0,0,1),
- tfn_vector(1,0,0));
- fail += check_transformation(cell, tfn, 1, NULL);
- tfn_free(tfn);
+ intmat_set_all_3x3(tfn, 0,0,1,
+ 1,0,0,
+ 0,1,0);
+ fail += check_transformation(cell, tfn, 1);
/* Doubling of cell in one direction */
- tfn = tfn_identity();
if ( tfn == NULL ) return 1;
- tfn_combine(tfn, tfn_vector(2,0,0),
- tfn_vector(0,1,0),
- tfn_vector(0,0,1));
- fail += check_transformation(cell, tfn, 0, NULL);
- tfn_free(tfn);
-
- /* Diagonal supercell */
- tfn = tfn_identity();
+ intmat_set_all_3x3(tfn, 2,0,0,
+ 0,1,0,
+ 0,0,1);
+ fail += check_transformation(cell, tfn, 0);
+
+ /* Shearing */
if ( tfn == NULL ) return 1;
- tfn_combine(tfn, tfn_vector(1,1,0),
- tfn_vector(0,1,0),
- tfn_vector(0,0,1));
- fail += check_transformation(cell, tfn, 1, NULL);
- tfn_free(tfn);
+ intmat_set_all_3x3(tfn, 1,0,0,
+ 1,1,0,
+ 0,0,1);
+ fail += check_transformation(cell, tfn, 1);
/* Crazy */
- tfn = tfn_identity();
if ( tfn == NULL ) return 1;
- tfn_combine(tfn, tfn_vector(1,1,0),
- tfn_vector(0,1,0),
- tfn_vector(0,1,1));
- fail += check_transformation(cell, tfn, 0, NULL);
- tfn_free(tfn);
+ intmat_set_all_3x3(tfn, 1,0,0,
+ 1,1,1,
+ 0,0,1);
+ fail += check_transformation(cell, tfn, 0);
/* Identity in two parts */
- tfn = tfn_identity();
+ part1 = intmat_identity(3);
+ part2 = intmat_identity(3);
if ( tfn == NULL ) return 1;
- tfn_combine(tfn, tfn_vector(0,0,1),
- tfn_vector(0,1,0),
- tfn_vector(-1,0,0));
- tfn_combine(tfn, tfn_vector(0,0,-1),
- tfn_vector(0,1,0),
- tfn_vector(1,0,0));
+ intmat_set_all_3x3(part1, 0,0,-1,
+ 0,1,0,
+ 1,0,0);
+ intmat_set_all_3x3(part2, 0,0,1,
+ 0,1,0,
+ -1,0,0);
+ tfn = intmat_intmat_mult(part1, part2);
fail += check_identity(cell, tfn);
- tfn_free(tfn);
+ intmat_free(part1);
+ intmat_free(part2);
+
+ intmat_free(tfn);
/* Check some uncentering transformations */
cref = cell_new_from_parameters(50e-10, 50e-10, 50e-10,