aboutsummaryrefslogtreecommitdiff
path: root/libcrystfel/src/symmetry.c
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2012-10-19 10:55:40 -0700
committerThomas White <taw@physics.org>2012-10-19 10:55:40 -0700
commit673dae374edf54c04d41f44e0f95041d5cf1cc7a (patch)
tree11164757434366667cd216d065d2f1f010651042 /libcrystfel/src/symmetry.c
parentec5b87bcfc83b3f2a38202ce26184c35adf870f7 (diff)
Convert SymOpList to use IntegerMatrix
This simplifies things a lot
Diffstat (limited to 'libcrystfel/src/symmetry.c')
-rw-r--r--libcrystfel/src/symmetry.c887
1 files changed, 419 insertions, 468 deletions
diff --git a/libcrystfel/src/symmetry.c b/libcrystfel/src/symmetry.c
index 8a8a6184..db0073c9 100644
--- a/libcrystfel/src/symmetry.c
+++ b/libcrystfel/src/symmetry.c
@@ -54,18 +54,9 @@
*/
-struct sym_op
-{
- signed int *h;
- signed int *k;
- signed int *l; /* Contributions to h, k and l from h, k and l */
- int order;
-};
-
-
struct _symoplist
{
- struct sym_op *ops;
+ IntegerMatrix **ops;
int n_ops;
int max_ops;
char *name;
@@ -83,7 +74,7 @@ struct _symopmask
static void alloc_ops(SymOpList *ops)
{
- ops->ops = realloc(ops->ops, ops->max_ops*sizeof(struct sym_op));
+ ops->ops = realloc(ops->ops, ops->max_ops*sizeof(IntegerMatrix *));
}
@@ -145,9 +136,7 @@ void free_symoplist(SymOpList *ops)
if ( ops == NULL ) return;
for ( i=0; i<ops->n_ops; i++ ) {
- free(ops->ops[i].h);
- free(ops->ops[i].k);
- free(ops->ops[i].l);
+ intmat_free(ops->ops[i]);
}
if ( ops->ops != NULL ) free(ops->ops);
if ( ops->name != NULL ) free(ops->name);
@@ -176,55 +165,53 @@ static int num_ops(const SymOpList *ops)
}
-/* Add a operation to a SymOpList */
-static void add_symop(SymOpList *ops,
- signed int *h, signed int *k, signed int *l,
- int order)
+/**
+ * add_symop:
+ * @ops: A %SymOpList
+ * @m: An %IntegerMatrix
+ *
+ * Adds @m to @ops.
+ **/
+void add_symop(SymOpList *ops, IntegerMatrix *m)
{
- int n;
-
if ( ops->n_ops == ops->max_ops ) {
- /* Pretty sure this never happens, but still... */
ops->max_ops += 16;
alloc_ops(ops);
}
- n = ops->n_ops;
- ops->ops[n].h = h;
- ops->ops[n].k = k;
- ops->ops[n].l = l;
- ops->ops[n].order = order;
- ops->n_ops++;
+ ops->ops[ops->n_ops++] = m;
}
-/* Add a operation to a SymOpList */
-static void add_copied_op(SymOpList *ops, struct sym_op *copyme)
+/* Add a operation to a SymOpList, starting from v(..) */
+static void add_symop_v(SymOpList *ops,
+ signed int *h, signed int *k, signed int *l)
{
- int n;
- signed int *h, *k, *l;
+ IntegerMatrix *m;
+ int i;
- if ( ops->n_ops == ops->max_ops ) {
- ops->max_ops += 16;
- alloc_ops(ops);
- }
+ m = intmat_new(3, 3);
+ assert(m != NULL);
- n = ops->n_ops;
+ for ( i=0; i<3; i++ ) intmat_set(m, 0, i, h[i]);
+ for ( i=0; i<3; i++ ) intmat_set(m, 1, i, k[i]);
+ for ( i=0; i<3; i++ ) intmat_set(m, 2, i, l[i]);
- h = malloc(3*sizeof(signed int));
- k = malloc(3*sizeof(signed int));
- l = malloc(3*sizeof(signed int));
+ free(h);
+ free(k);
+ free(l);
- memcpy(h, copyme->h, 3*sizeof(signed int));
- memcpy(k, copyme->k, 3*sizeof(signed int));
- memcpy(l, copyme->l, 3*sizeof(signed int));
+ add_symop(ops, m);
+}
- ops->ops[n].h = h;
- ops->ops[n].k = k;
- ops->ops[n].l = l;
- ops->ops[n].order = copyme->order;
- ops->n_ops++;
+static signed int *v(signed int h, signed int k, signed int i, signed int l)
+{
+ signed int *vec = malloc(3*sizeof(signed int));
+ if ( vec == NULL ) return NULL;
+ /* Convert back to 3-index form now */
+ vec[0] = h-i; vec[1] = k-i; vec[2] = l;
+ return vec;
}
@@ -254,139 +241,88 @@ int num_equivs(const SymOpList *ops, const SymOpMask *m)
}
-static signed int *v(signed int h, signed int k, signed int i, signed int l)
+static void add_identity(SymOpList *s)
{
- signed int *vec = malloc(3*sizeof(signed int));
- if ( vec == NULL ) return NULL;
- /* Convert back to 3-index form now */
- vec[0] = h-i; vec[1] = k-i; vec[2] = l;
- return vec;
-}
-
-
-static void combine_ops(signed int *h1, signed int *k1, signed int *l1,
- signed int *h2, signed int *k2, signed int *l2,
- signed int *hnew, signed int *knew, signed int *lnew)
-{
- /* Yay matrices */
- hnew[0] = h1[0]*h2[0] + h1[1]*k2[0] + h1[2]*l2[0];
- hnew[1] = h1[0]*h2[1] + h1[1]*k2[1] + h1[2]*l2[1];
- hnew[2] = h1[0]*h2[2] + h1[1]*k2[2] + h1[2]*l2[2];
-
- knew[0] = k1[0]*h2[0] + k1[1]*k2[0] + k1[2]*l2[0];
- knew[1] = k1[0]*h2[1] + k1[1]*k2[1] + k1[2]*l2[1];
- knew[2] = k1[0]*h2[2] + k1[1]*k2[2] + k1[2]*l2[2];
+ int i, ni;
+ int found;
- lnew[0] = l1[0]*h2[0] + l1[1]*k2[0] + l1[2]*l2[0];
- lnew[1] = l1[0]*h2[1] + l1[1]*k2[1] + l1[2]*l2[1];
- lnew[2] = l1[0]*h2[2] + l1[1]*k2[2] + l1[2]*l2[2];
+ found = 0;
+ ni = num_ops(s);
+ for ( i=0; i<ni; i++ ) {
+ if ( intmat_is_identity(s->ops[i]) ) {
+ found = 1;
+ break;
+ }
+ }
+ if ( !found ) {
+ add_symop_v(s, v(1,0,0,0), v(0,1,0,0), v(0,0,0,1)); /* I */
+ }
}
-static void combine_and_add_symop(struct sym_op *opi, int oi,
- struct sym_op *opj,
- SymOpList *s)
+/* Fill in the other operations for a point group starting from its
+ * generators */
+static void expand_ops(SymOpList *s)
{
- int i;
- signed int *h, *k, *l;
-
- h = malloc(3*sizeof(signed int));
- k = malloc(3*sizeof(signed int));
- l = malloc(3*sizeof(signed int));
- assert(h != NULL);
- assert(k != NULL);
- assert(l != NULL);
-
- memcpy(h, opj->h, 3*sizeof(signed int));
- memcpy(k, opj->k, 3*sizeof(signed int));
- memcpy(l, opj->l, 3*sizeof(signed int));
-
- for ( i=0; i<oi; i++ ) {
-
- signed int hfs[3], kfs[3], lfs[3];
+ int added;
- combine_ops(h, k, l, opi->h, opi->k, opi->l, hfs, kfs, lfs);
+ add_identity(s);
- memcpy(h, hfs, 3*sizeof(signed int));
- memcpy(k, kfs, 3*sizeof(signed int));
- memcpy(l, lfs, 3*sizeof(signed int));
-
- }
-
-// STATUS("Creating %3i %3i %3i\n", h[0], h[1], h[2]);
-// STATUS(" %3i %3i %3i\n", k[0], k[1], k[2]);
-// STATUS(" %3i %3i %3i\n", l[0], l[1], l[2]);
+ do {
- add_symop(s, h, k, l, 1);
-}
+ int i, ni;
+ added = 0;
-/* Fill in the other operations for a point group starting from its
- * generators */
-static SymOpList *expand_ops(SymOpList *s)
-{
- int n, i;
- SymOpList *e;
+ ni = num_ops(s);
+ for ( i=0; i<ni; i++ ) {
- e = new_symoplist();
- if ( e == NULL ) return NULL;
- e->name = strdup(symmetry_name(s));
+ int j;
+ IntegerMatrix *opi = s->ops[i];
- add_symop(e, v(1,0,0,0), v(0,1,0,0), v(0,0,0,1), 1); /* I */
+ /* Apply op 'i' to all the current ops in the list */
+ for ( j=0; j<ni; j++ ) {
- n = num_ops(s);
- for ( i=0; i<n; i++ ) {
+ IntegerMatrix *opj = s->ops[j];
+ IntegerMatrix *m;
+ int k, nk;
+ int found;
- int j, nj;
- struct sym_op *opi = &s->ops[i];
+ m = intmat_intmat_mult(opi, opj);
+ assert(m != NULL);
- /* Apply op 'i' to all the current ops in the list */
- nj = num_ops(e);
- for ( j=0; j<nj; j++ ) {
+ nk = num_ops(s);
+ found = 0;
+ for ( k=0; k<nk; k++ ) {
+ if ( intmat_equals(m, s->ops[k]) ) {
+ found = 1;
+ intmat_free(m);
+ break;
+ }
+ }
- int oi;
+ if ( !found ) {
+ add_symop(s, m);
+ added++;
+ }
- for ( oi=0; oi<opi->order-1; oi++ ) {
- combine_and_add_symop(opi, oi+1, &e->ops[j], e);
}
}
- }
-
- free_symoplist(s);
-
- return e;
+ } while ( added );
}
/* Transform all the operations in a SymOpList by a given matrix.
* The matrix must have a determinant of +/- 1 (otherwise its inverse would
* not also be an integer matrix). */
-static void transform_ops(SymOpList *s, signed int *na,
- signed int *nb,
- signed int *nc)
+static void transform_ops(SymOpList *s, IntegerMatrix *t)
{
int n, i;
- IntegerMatrix *t, *inv;
+ IntegerMatrix *inv;
signed int det;
- t = intmat_new(3, 3);
- if ( t == NULL ) {
- ERROR("Failed to allocate matrix.\n");
- return;
- }
-
- intmat_set(t, 0, 0, na[0]);
- intmat_set(t, 1, 0, na[1]);
- intmat_set(t, 2, 0, na[2]);
- intmat_set(t, 0, 1, nb[0]);
- intmat_set(t, 1, 1, nb[1]);
- intmat_set(t, 2, 1, nb[2]);
- intmat_set(t, 0, 2, nc[0]);
- intmat_set(t, 1, 2, nc[1]);
- intmat_set(t, 2, 2, nc[2]);
-
det = intmat_det(t);
if ( det == -1 ) {
ERROR("Warning: mirrored SymOpList.\n");
@@ -404,30 +340,13 @@ static void transform_ops(SymOpList *s, signed int *na,
n = num_ops(s);
for ( i=0; i<n; i++ ) {
- IntegerMatrix *m, *r, *f;
-
- m = intmat_new(3, 3);
- if ( m == NULL ) {
- ERROR("Failed to allocate matrix.\n");
- return;
- }
+ IntegerMatrix *r, *f;
- intmat_set(m, 0, 0, s->ops[i].h[0]);
- intmat_set(m, 1, 0, s->ops[i].h[1]);
- intmat_set(m, 2, 0, s->ops[i].h[2]);
- intmat_set(m, 0, 1, s->ops[i].k[0]);
- intmat_set(m, 1, 1, s->ops[i].k[1]);
- intmat_set(m, 2, 1, s->ops[i].k[2]);
- intmat_set(m, 0, 2, s->ops[i].l[0]);
- intmat_set(m, 1, 2, s->ops[i].l[1]);
- intmat_set(m, 2, 2, s->ops[i].l[2]);
-
- r = intmat_intmat_mult(m, t);
+ r = intmat_intmat_mult(s->ops[i], t);
if ( r == NULL ) {
ERROR("Matrix multiplication failed.\n");
return;
}
- intmat_free(m);
f = intmat_intmat_mult(inv, r);
if ( f == NULL ) {
@@ -436,20 +355,12 @@ static void transform_ops(SymOpList *s, signed int *na,
}
intmat_free(r);
- s->ops[i].h[0] = intmat_get(f, 0, 0);
- s->ops[i].h[1] = intmat_get(f, 1, 0);
- s->ops[i].h[2] = intmat_get(f, 2, 0);
- s->ops[i].k[0] = intmat_get(f, 0, 1);
- s->ops[i].k[1] = intmat_get(f, 1, 1);
- s->ops[i].k[2] = intmat_get(f, 2, 1);
- s->ops[i].l[0] = intmat_get(f, 0, 2);
- s->ops[i].l[1] = intmat_get(f, 1, 2);
- s->ops[i].l[2] = intmat_get(f, 2, 2);
+ intmat_free(s->ops[i]);
+ s->ops[i] = intmat_copy(f);
intmat_free(f);
}
- intmat_free(t);
intmat_free(inv);
}
@@ -459,9 +370,10 @@ static void transform_ops(SymOpList *s, signed int *na,
static SymOpList *make_1bar()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1), 2); /* -I */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1)); /* -I */
new->name = strdup("-1");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
@@ -469,7 +381,8 @@ static SymOpList *make_1()
{
SymOpList *new = new_symoplist();
new->name = strdup("1");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
@@ -478,28 +391,31 @@ static SymOpList *make_1()
static SymOpList *make_2m()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1), 2); /* 2 // l */
- add_symop(new, v(1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2); /* m -| l */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1)); /* 2 // l */
+ add_symop_v(new, v(1,0,0,0), v(0,1,0,0), v(0,0,0,-1)); /* m -| l */
new->name = strdup("2/m");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_2()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1), 2); /* 2 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1)); /* 2 // l */
new->name = strdup("2");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_m()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2); /* m -| l */
+ add_symop_v(new, v(1,0,0,0), v(0,1,0,0), v(0,0,0,-1)); /* m -| l */
new->name = strdup("m");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
@@ -508,31 +424,34 @@ static SymOpList *make_m()
static SymOpList *make_mmm()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1), 2); /* 2 // l */
- add_symop(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2); /* 2 // k */
- add_symop(new, v(1,0,0,0), v(0,-1,0,0), v(0,0,0,1), 2); /* m -| k */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1)); /* 2 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1)); /* 2 // k */
+ add_symop_v(new, v(1,0,0,0), v(0,-1,0,0), v(0,0,0,1)); /* m -| k */
new->name = strdup("mmm");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_222()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1), 2); /* 2 // l */
- add_symop(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2); /* 2 // k */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1)); /* 2 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1)); /* 2 // k */
new->name = strdup("222");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_mm2()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1), 2); /* 2 // l */
- add_symop(new, v(1,0,0,0), v(0,-1,0,0), v(0,0,0,1), 2); /* m -| k */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1)); /* 2 // l */
+ add_symop_v(new, v(1,0,0,0), v(0,-1,0,0), v(0,0,0,1)); /* m -| k */
new->name = strdup("mm2");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
@@ -541,79 +460,87 @@ static SymOpList *make_mm2()
static SymOpList *make_4m()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1), 4); /* 4 // l */
- add_symop(new, v(1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2); /* m -| l */
+ add_symop_v(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1)); /* 4 // l */
+ add_symop_v(new, v(1,0,0,0), v(0,1,0,0), v(0,0,0,-1)); /* m -| l */
new->name = strdup("4/m");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_4()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1), 4); /* 4 // l */
+ add_symop_v(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1)); /* 4 // l */
new->name = strdup("4");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_4mm()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1), 4); /* 4 // l */
- add_symop(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,1), 2); /* m -| l */
+ add_symop_v(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1)); /* 4 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,1)); /* m -| l */
new->name = strdup("4mm");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_422()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1), 4); /* 4 // l */
- add_symop(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2); /* 2 // k */
+ add_symop_v(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1)); /* 4 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1)); /* 2 // k */
new->name = strdup("422");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_4bar()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,1,0,0), v(-1,0,0,0), v(0,0,0,-1), 4); /* -4 // l */
+ add_symop_v(new, v(0,1,0,0), v(-1,0,0,0), v(0,0,0,-1)); /* -4 // l */
new->name = strdup("-4");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_4bar2m()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,1,0,0), v(-1,0,0,0), v(0,0,0,-1), 4); /* -4 // l */
- add_symop(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2); /* 2 // k */
+ add_symop_v(new, v(0,1,0,0), v(-1,0,0,0), v(0,0,0,-1)); /* -4 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1)); /* 2 // k */
new->name = strdup("-42m");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_4barm2()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,1,0,0), v(-1,0,0,0), v(0,0,0,-1), 4); /* -4 // l */
- add_symop(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,-1), 2); /* 2 // h+k */
+ add_symop_v(new, v(0,1,0,0), v(-1,0,0,0), v(0,0,0,-1)); /* -4 // l */
+ add_symop_v(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,-1)); /* 2 // h+k */
new->name = strdup("-4m2");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_4mmm()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1), 4); /* 4 // l */
- add_symop(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,1), 2); /* m -| k */
- add_symop(new, v(1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2); /* m -| l */
+ add_symop_v(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1)); /* 4 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,1)); /* m -| k */
+ add_symop_v(new, v(1,0,0,0), v(0,1,0,0), v(0,0,0,-1)); /* m -| l */
new->name = strdup("4/mmm");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
@@ -622,50 +549,55 @@ static SymOpList *make_4mmm()
static SymOpList *make_3_R()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,0,1), v(1,0,0,0), v(0,1,0,0), 3); /* 3 // h+k+l */
+ add_symop_v(new, v(0,0,0,1), v(1,0,0,0), v(0,1,0,0)); /* 3 // h+k+l */
new->name = strdup("3_R");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_3bar_R()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,0,1), v(1,0,0,0), v(0,1,0,0), 3); /* -3 // h+k+l */
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1), 2); /* -I */
+ add_symop_v(new, v(0,0,0,1), v(1,0,0,0), v(0,1,0,0)); /* -3 // h+k+l */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1)); /* -I */
new->name = strdup("-3_R");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_32_R()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,0,1), v(1,0,0,0), v(0,1,0,0), 3); /* 3 // h+k+l */
- add_symop(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,-1), 2); /* 2 -| 3 */
+ add_symop_v(new, v(0,0,0,1), v(1,0,0,0), v(0,1,0,0)); /* 3 // h+k+l */
+ add_symop_v(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,-1)); /* 2 -| 3 */
new->name = strdup("32_R");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_3m_R()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,0,1), v(1,0,0,0), v(0,1,0,0), 3); /* 3 // h+k+l */
- add_symop(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,1), 2); /* m */
+ add_symop_v(new, v(0,0,0,1), v(1,0,0,0), v(0,1,0,0)); /* 3 // h+k+l */
+ add_symop_v(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,1)); /* m */
new->name = strdup("3m_R");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_3barm_R()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,0,1), v(1,0,0,0), v(0,1,0,0), 3); /* -3 // h+k+l */
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1), 2); /* -I */
- add_symop(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,1), 2); /* m */
+ add_symop_v(new, v(0,0,0,1), v(1,0,0,0), v(0,1,0,0)); /* -3 // h+k+l */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1)); /* -I */
+ add_symop_v(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,1)); /* m */
new->name = strdup("-3m_R");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
@@ -674,81 +606,89 @@ static SymOpList *make_3barm_R()
static SymOpList *make_3_H()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1), 3); /* 3 // l */
+ add_symop_v(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1)); /* 3 // l */
new->name = strdup("3_H");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_3bar_H()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1), 3); /* 3 // l */
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1), 2); /* -I */
+ add_symop_v(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1)); /* 3 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1)); /* -I */
new->name = strdup("-3_H");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_321_H()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1), 3); /* 3 // l */
- add_symop(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,-1), 2); /* 2 // h */
+ add_symop_v(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1)); /* 3 // l */
+ add_symop_v(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,-1)); /* 2 // h */
new->name = strdup("321_H");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_312_H()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1), 3); /* 3 // l */
- add_symop(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,-1), 2); /* 2 // h+k */
+ add_symop_v(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1)); /* 3 // l */
+ add_symop_v(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,-1)); /* 2 // h+k */
new->name = strdup("312_H");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_3m1_H()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1), 3); /* 3 // l */
- add_symop(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,1), 2); /* m -| i */
+ add_symop_v(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1)); /* 3 // l */
+ add_symop_v(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,1)); /* m -| i */
new->name = strdup("3m1_H");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_31m_H()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1), 3); /* 3 // l */
- add_symop(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,1), 2); /* m -| (k+i) */
+ add_symop_v(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1)); /* 3 // l */
+ add_symop_v(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,1)); /* m -| (k+i) */
new->name = strdup("31m_H");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_3barm1_H()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1), 3); /* 3 // l */
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1), 2); /* -I */
- add_symop(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,-1), 2); /* 2 // h */
+ add_symop_v(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1)); /* 3 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1)); /* -I */
+ add_symop_v(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,-1)); /* 2 // h */
new->name = strdup("-3m1_H");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_3bar1m_H()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1), 3); /* 3 // l */
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1), 2); /* -I */
- add_symop(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,-1), 2); /* 2 // h+k */
+ add_symop_v(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,1)); /* 3 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1)); /* -I */
+ add_symop_v(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,-1)); /* 2 // h+k */
new->name = strdup("-31m_H");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
@@ -757,79 +697,87 @@ static SymOpList *make_3bar1m_H()
static SymOpList *make_6()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,-1,0), v(-1,0,0,0), v(0,0,0,1), 6); /* 6 // l */
+ add_symop_v(new, v(0,0,-1,0), v(-1,0,0,0), v(0,0,0,1)); /* 6 // l */
new->name = strdup("6");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_6bar()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,-1), 6); /* -6 // l */
+ add_symop_v(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,-1)); /* -6 // l */
new->name = strdup("-6");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_6m()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,-1,0), v(-1,0,0,0), v(0,0,0,1), 6); /* 6 // l */
- add_symop(new, v(1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2); /* m -| l */
+ add_symop_v(new, v(0,0,-1,0), v(-1,0,0,0), v(0,0,0,1)); /* 6 // l */
+ add_symop_v(new, v(1,0,0,0), v(0,1,0,0), v(0,0,0,-1)); /* m -| l */
new->name = strdup("6/m");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_622()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,-1,0), v(-1,0,0,0), v(0,0,0,1), 6); /* 6 // l */
- add_symop(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,-1), 2); /* 2 // h */
+ add_symop_v(new, v(0,0,-1,0), v(-1,0,0,0), v(0,0,0,1)); /* 6 // l */
+ add_symop_v(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,-1)); /* 2 // h */
new->name = strdup("622");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_6mm()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,-1,0), v(-1,0,0,0), v(0,0,0,1), 6); /* 6 // l */
- add_symop(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,1), 2); /* m -| i */
+ add_symop_v(new, v(0,0,-1,0), v(-1,0,0,0), v(0,0,0,1)); /* 6 // l */
+ add_symop_v(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,1)); /* m -| i */
new->name = strdup("6mm");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_6barm2()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,-1), 6); /* -6 // l */
- add_symop(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,1), 2); /* m -| i */
+ add_symop_v(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,-1)); /* -6 // l */
+ add_symop_v(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,1)); /* m -| i */
new->name = strdup("-6m2");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_6bar2m()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,-1), 6); /* -6 // l */
- add_symop(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,1), 2); /* m -| (k+i) */
+ add_symop_v(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,-1)); /* -6 // l */
+ add_symop_v(new, v(0,1,0,0), v(1,0,0,0), v(0,0,0,1)); /* m -| (k+i) */
new->name = strdup("-62m");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_6mmm()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,-1), 6); /* -6 // l */
- add_symop(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,1), 2); /* m -| i */
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1), 2); /* -I */
+ add_symop_v(new, v(0,0,1,0), v(1,0,0,0), v(0,0,0,-1)); /* -6 // l */
+ add_symop_v(new, v(0,-1,0,0), v(-1,0,0,0), v(0,0,0,1)); /* m -| i */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1)); /* -I */
new->name = strdup("6/mmm");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
@@ -838,57 +786,62 @@ static SymOpList *make_6mmm()
static SymOpList *make_23()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1), 2); /* 2// l */
- add_symop(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2); /* 2// k */
- add_symop(new, v(0,1,0,0), v(0,0,0,1), v(1,0,0,0), 3); /* 3// h+k+l */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1)); /* 2 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1)); /* 2 // k */
+ add_symop_v(new, v(0,1,0,0), v(0,0,0,1), v(1,0,0,0)); /* 3 // h+k+l */
new->name = strdup("23");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_m3bar()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1), 2); /* 2// l */
- add_symop(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2); /* 2// k */
- add_symop(new, v(0,1,0,0), v(0,0,0,1), v(1,0,0,0), 3); /* 3// h+k+l */
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1), 2); /* -I */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,1)); /* 2 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1)); /* 2 // k */
+ add_symop_v(new, v(0,1,0,0), v(0,0,0,1), v(1,0,0,0)); /* 3 // h+k+l */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1)); /* -I */
new->name = strdup("m-3");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_432()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1), 4); /* 4 // l */
- add_symop(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2);/* 2 // k */
- add_symop(new, v(0,1,0,0), v(0,0,0,1), v(1,0,0,0), 3); /* 3 // h+k+l */
+ add_symop_v(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1)); /* 4 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1));/* 2 // k */
+ add_symop_v(new, v(0,1,0,0), v(0,0,0,1), v(1,0,0,0)); /* 3 // h+k+l */
new->name = strdup("432");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_4bar3m()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,1,0,0), v(-1,0,0,0), v(0,0,0,-1), 4); /* -4 // l */
- add_symop(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2);/* 2 // k */
- add_symop(new, v(0,1,0,0), v(0,0,0,1), v(1,0,0,0), 3); /* 3 // h+k+l */
+ add_symop_v(new, v(0,1,0,0), v(-1,0,0,0), v(0,0,0,-1)); /* -4 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1)); /* 2 // k */
+ add_symop_v(new, v(0,1,0,0), v(0,0,0,1), v(1,0,0,0)); /* 3 // h+k+l */
new->name = strdup("-43m");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
static SymOpList *make_m3barm()
{
SymOpList *new = new_symoplist();
- add_symop(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1), 4); /* 4 // l */
- add_symop(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1), 2);/* 2 // k */
- add_symop(new, v(0,1,0,0), v(0,0,0,1), v(1,0,0,0), 3); /* 3 // h+k+l */
- add_symop(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1), 2); /* -I */
+ add_symop_v(new, v(0,-1,0,0), v(1,0,0,0), v(0,0,0,1)); /* 4 // l */
+ add_symop_v(new, v(-1,0,0,0), v(0,1,0,0), v(0,0,0,-1));/* 2 // k */
+ add_symop_v(new, v(0,1,0,0), v(0,0,0,1), v(1,0,0,0)); /* 3 // h+k+l */
+ add_symop_v(new, v(-1,0,0,0), v(0,-1,0,0), v(0,0,0,-1)); /* -I */
new->name = strdup("m-3m");
- return expand_ops(new);
+ expand_ops(new);
+ return new;
}
@@ -976,6 +929,7 @@ static SymOpList *getpg_arbitrary_ua(const char *sym, size_t s)
char ua;
char *pg_type;
SymOpList *pg;
+ IntegerMatrix *t;
if ( strncmp(sym+s, "ua", 2) == 0 ) {
ua = sym[s+2];
@@ -998,22 +952,28 @@ static SymOpList *getpg_arbitrary_ua(const char *sym, size_t s)
}
free(pg_type);
+ t = intmat_new(3, 3);
+ if ( t == NULL ) return NULL;
+
switch ( ua ) {
case 'a' :
- transform_ops(pg, v(0,0,0,1),
- v(0,1,0,0),
- v(-1,0,0,0));
+ intmat_set(t, 0, 2, 1);
+ intmat_set(t, 1, 1, 1);
+ intmat_set(t, 2, 0, -1);
break;
case 'b' :
- transform_ops(pg, v(1,0,0,0),
- v(0,0,0,1),
- v(0,-1,0,0));
+ intmat_set(t, 0, 0, 1);
+ intmat_set(t, 1, 2, 1);
+ intmat_set(t, 2, 1, -1);
+
break;
case 'c' :
- /* No transformation needed */
+ intmat_set(t, 0, 0, 1);
+ intmat_set(t, 1, 1, 1);
+ intmat_set(t, 2, 2, 1);
break;
default :
@@ -1023,6 +983,9 @@ static SymOpList *getpg_arbitrary_ua(const char *sym, size_t s)
}
+ transform_ops(pg, t);
+ intmat_free(t);
+
return pg;
}
@@ -1074,13 +1037,20 @@ SymOpList *get_pointgroup(const char *sym)
}
-static void do_op(const struct sym_op *op,
+static void do_op(const IntegerMatrix *op,
signed int h, signed int k, signed int l,
signed int *he, signed int *ke, signed int *le)
{
- *he = h*op->h[0] + k*op->h[1] + l*op->h[2];
- *ke = h*op->k[0] + k*op->k[1] + l*op->k[2];
- *le = h*op->l[0] + k*op->l[1] + l*op->l[2];
+ signed int v[3];
+ signed int *ans;
+
+ v[0] = h; v[1] = k; v[2] = l;
+
+ ans = intmat_intvec_mult(op, v);
+ assert(ans != NULL);
+
+ *he = ans[0]; *ke = ans[1]; *le = ans[2];
+ free(ans);
}
@@ -1119,7 +1089,7 @@ void get_equiv(const SymOpList *ops, const SymOpMask *m, int idx,
for ( i=0; i<n; i++ ) {
if ( (c == idx) && m->mask[i] ) {
- do_op(&ops->ops[i], h, k, l, he, ke, le);
+ do_op(ops->ops[i], h, k, l, he, ke, le);
return;
}
@@ -1151,7 +1121,7 @@ void get_equiv(const SymOpList *ops, const SymOpMask *m, int idx,
}
- do_op(&ops->ops[idx], h, k, l, he, ke, le);
+ do_op(ops->ops[idx], h, k, l, he, ke, le);
}
@@ -1297,36 +1267,6 @@ void get_asymm(const SymOpList *ops,
}
-static int is_inversion(const struct sym_op *op)
-{
- if ( (op->h[0]!=-1) || (op->h[1]!=0) || (op->h[2]!=0) ) return 0;
- if ( (op->k[0]!=0) || (op->k[1]!=-1) || (op->k[2]!=0) ) return 0;
- if ( (op->l[0]!=0) || (op->l[1]!=0) || (op->l[2]!=-1) ) return 0;
- return 1;
-}
-
-
-static int is_identity(const struct sym_op *op)
-{
- if ( (op->h[0]!=1) || (op->h[1]!=0) || (op->h[2]!=0) ) return 0;
- if ( (op->k[0]!=0) || (op->k[1]!=1) || (op->k[2]!=0) ) return 0;
- if ( (op->l[0]!=0) || (op->l[1]!=0) || (op->l[2]!=1) ) return 0;
- return 1;
-}
-
-
-static signed int determinant(const struct sym_op *op)
-{
- signed int det = 0;
-
- det += op->h[0] * (op->k[1]*op->l[2] - op->k[2]*op->l[1]);
- det -= op->h[1] * (op->k[0]*op->l[2] - op->k[2]*op->l[0]);
- det += op->h[2] * (op->k[0]*op->l[1] - op->k[1]*op->l[0]);
-
- return det;
-}
-
-
/**
* is_centrosymmetric:
* @s: A %SymOpList
@@ -1339,49 +1279,25 @@ int is_centrosymmetric(const SymOpList *s)
n = num_ops(s);
for ( i=0; i<n; i++ ) {
- if ( is_inversion(&s->ops[i]) ) return 1;
+ if ( intmat_is_inversion(s->ops[i]) ) return 1;
}
return 0;
}
-static int ops_equal(const struct sym_op *op,
- signed int *h, signed int *k, signed int *l)
-{
- if ( (op->h[0]!=h[0]) || (op->h[1]!=h[1]) || (op->h[2]!=h[2]) )
- return 0;
- if ( (op->k[0]!=k[0]) || (op->k[1]!=k[1]) || (op->k[2]!=k[2]) )
- return 0;
- if ( (op->l[0]!=l[0]) || (op->l[1]!=l[1]) || (op->l[2]!=l[2]) )
- return 0;
- return 1;
-}
-
-
-static int struct_ops_equal(const struct sym_op *op1, const struct sym_op *op2)
-{
- return ops_equal(op1, op2->h, op2->k, op2->l);
-}
-
-
/* Return true if a*b = ans */
-static int check_mult(const struct sym_op *ans,
- const struct sym_op *a, const struct sym_op *b)
+static int check_mult(const IntegerMatrix *ans,
+ const IntegerMatrix *a, const IntegerMatrix *b)
{
- signed int *ans_h, *ans_k, *ans_l;
int val;
+ IntegerMatrix *m;
- ans_h = malloc(3*sizeof(signed int));
- ans_k = malloc(3*sizeof(signed int));
- ans_l = malloc(3*sizeof(signed int));
+ m = intmat_intmat_mult(a, b);
+ assert(m != NULL);
- combine_ops(a->h, a->k, a->l, b->h, b->k, b->l, ans_h, ans_k, ans_l);
- val = ops_equal(ans, ans_h, ans_k, ans_l);
-
- free(ans_h);
- free(ans_k);
- free(ans_l);
+ val = intmat_equals(ans, m);
+ intmat_free(m);
return val;
}
@@ -1409,9 +1325,7 @@ int is_subgroup(const SymOpList *source, const SymOpList *target)
for ( j=0; j<n_src; j++ ) {
- if ( struct_ops_equal(&target->ops[i],
- &source->ops[j] ) )
- {
+ if ( intmat_equals(target->ops[i], source->ops[j]) ) {
found = 1;
break;
}
@@ -1426,52 +1340,52 @@ int is_subgroup(const SymOpList *source, const SymOpList *target)
}
-/**
- * get_ambiguities:
- * @source: The "source" symmetry, a %SymOpList
- * @target: The "target" symmetry, a %SymOpList
-
- * Calculates twinning laws. Returns a %SymOpList containing the twinning
- * operators, which are the symmetry operations which can be added to @target
- * to generate @source. Only rotations are allowable - no mirrors nor
- * inversions.
- * To count the number of possibilities, use num_ops() on the result.
- *
- * Returns: A %SymOpList containing the twinning operators, or NULL if the
- * source symmetry cannot be generated from that target symmetry without using
- * mirror or inversion operations.
- */
-SymOpList *get_ambiguities(const SymOpList *source, const SymOpList *target)
+/* Returns n, where m^n = I */
+static int order(const IntegerMatrix *m)
{
- int n_src, n_tgt;
+ IntegerMatrix *a;
int i;
- SymOpList *twins;
- SymOpList *src_reordered;
- SymOpMask *used;
- char *name;
- n_src = num_ops(source);
- n_tgt = num_ops(target);
+ a = intmat_new(3, 3);
+ assert(a != NULL);
+ intmat_set(a, 0, 0, 1);
+ intmat_set(a, 1, 1, 1);
+ intmat_set(a, 2, 2, 1);
- if ( !is_subgroup(source, target) ) {
- ERROR("'%s' is not a subgroup of '%s'\n",
- symmetry_name(target), symmetry_name(source));
- return NULL;
- }
+ i = 0;
+ do {
- if ( n_src % n_tgt != 0 ) {
- ERROR("Subgroup index would be fractional.\n");
- return NULL;
- }
+ IntegerMatrix *anew;
+
+ anew = intmat_intmat_mult(m, a);
+ assert(anew != NULL);
+ intmat_free(a);
+ a = anew;
+
+ i++;
+
+ } while ( !intmat_is_identity(a) );
+
+ return i;
+}
+
+
+static SymOpList *flack_reorder(const SymOpList *source)
+{
+ SymOpList *src_reordered;
+ SymOpMask *used;
+ int i, n_src;
src_reordered = new_symoplist();
used = new_symopmask(source);
+ n_src = num_ops(source);
+
/* Find identity */
for ( i=0; i<n_src; i++ ) {
if ( used->mask[i] == 0 ) continue;
- if ( is_identity(&source->ops[i]) ) {
- add_copied_op(src_reordered, &source->ops[i]);
+ if ( intmat_is_identity(source->ops[i]) ) {
+ add_symop(src_reordered, intmat_copy(source->ops[i]));
used->mask[i] = 0;
}
}
@@ -1479,9 +1393,9 @@ SymOpList *get_ambiguities(const SymOpList *source, const SymOpList *target)
/* Find binary options (order=2) of first kind (determinant positive) */
for ( i=0; i<n_src; i++ ) {
if ( used->mask[i] == 0 ) continue;
- if ( (source->ops[i].order == 2)
- && (determinant(&source->ops[i]) > 0) ) {
- add_copied_op(src_reordered, &source->ops[i]);
+ if ( (order(source->ops[i]) == 2)
+ && (intmat_det(source->ops[i]) > 0) ) {
+ add_symop(src_reordered, intmat_copy(source->ops[i]));
used->mask[i] = 0;
}
}
@@ -1489,8 +1403,8 @@ SymOpList *get_ambiguities(const SymOpList *source, const SymOpList *target)
/* Find other operations of first kind (determinant positive) */
for ( i=0; i<n_src; i++ ) {
if ( used->mask[i] == 0 ) continue;
- if ( determinant(&source->ops[i]) > 0 ) {
- add_copied_op(src_reordered, &source->ops[i]);
+ if ( intmat_det(source->ops[i]) > 0 ) {
+ add_symop(src_reordered, intmat_copy(source->ops[i]));
used->mask[i] = 0;
}
}
@@ -1498,8 +1412,8 @@ SymOpList *get_ambiguities(const SymOpList *source, const SymOpList *target)
/* Find inversion */
for ( i=0; i<n_src; i++ ) {
if ( used->mask[i] == 0 ) continue;
- if ( is_inversion(&source->ops[i]) ) {
- add_copied_op(src_reordered, &source->ops[i]);
+ if ( intmat_is_inversion(source->ops[i]) ) {
+ add_symop(src_reordered, intmat_copy(source->ops[i]));
used->mask[i] = 0;
}
}
@@ -1507,9 +1421,9 @@ SymOpList *get_ambiguities(const SymOpList *source, const SymOpList *target)
/* Find binary options of second kind (determinant negative) */
for ( i=0; i<n_src; i++ ) {
if ( used->mask[i] == 0 ) continue;
- if ( (source->ops[i].order == 2)
- && (determinant(&source->ops[i]) < 0) ) {
- add_copied_op(src_reordered, &source->ops[i]);
+ if ( (order(source->ops[i]) == 2)
+ && (intmat_det(source->ops[i]) < 0) ) {
+ add_symop(src_reordered, intmat_copy(source->ops[i]));
used->mask[i] = 0;
}
}
@@ -1517,8 +1431,8 @@ SymOpList *get_ambiguities(const SymOpList *source, const SymOpList *target)
/* Find other operations of second kind (determinant negative) */
for ( i=0; i<n_src; i++ ) {
if ( used->mask[i] == 0 ) continue;
- if ( determinant(&source->ops[i]) < 0 ) {
- add_copied_op(src_reordered, &source->ops[i]);
+ if ( intmat_det(source->ops[i]) < 0 ) {
+ add_symop(src_reordered, intmat_copy(source->ops[i]));
used->mask[i] = 0;
}
}
@@ -1539,9 +1453,62 @@ SymOpList *get_ambiguities(const SymOpList *source, const SymOpList *target)
}
free_symopmask(used);
- used = new_symopmask(src_reordered);
- /* This is the first method from Flack (1987) */
+ return src_reordered;
+}
+
+
+/**
+ * get_ambiguities:
+ * @source: The "source" symmetry, a %SymOpList
+ * @target: The "target" symmetry, a %SymOpList
+
+ * Calculates twinning laws. Returns a %SymOpList containing the twinning
+ * operators, which are the symmetry operations which can be added to @target
+ * to generate @source. Only rotations are allowable - no mirrors nor
+ * inversions.
+ * To count the number of possibilities, use num_ops() on the result.
+ *
+ * The algorithm used is "Algorithm A" from Flack (1987), Acta Cryst A43 p564.
+ *
+ * Returns: A %SymOpList containing the twinning operators, or NULL if the
+ * source symmetry cannot be generated from that target symmetry without using
+ * mirror or inversion operations.
+ */
+SymOpList *get_ambiguities(const SymOpList *source, const SymOpList *target)
+{
+ int n_src, n_tgt;
+ int i;
+ SymOpList *twins;
+ SymOpList *src_reordered;
+ SymOpList *tgt_reordered;
+ SymOpMask *used;
+ char *name;
+
+ n_src = num_ops(source);
+ n_tgt = num_ops(target);
+
+ if ( !is_subgroup(source, target) ) {
+ ERROR("'%s' is not a subgroup of '%s'\n",
+ symmetry_name(target), symmetry_name(source));
+ return NULL;
+ }
+
+ if ( n_src % n_tgt != 0 ) {
+ ERROR("Subgroup index would be fractional.\n");
+ return NULL;
+ }
+
+ /* Reorder operations to prefer rotations in the output */
+ src_reordered = flack_reorder(source);
+ if ( src_reordered == NULL ) return NULL;
+
+ /* Reorder the subgroup as well, but strictly speaking we only need
+ * the identity at the beginning */
+ tgt_reordered = flack_reorder(target);
+ if ( tgt_reordered == NULL ) return NULL;
+
+ used = new_symopmask(src_reordered);
for ( i=0; i<n_src; i++ ) {
int j;
@@ -1551,9 +1518,9 @@ SymOpList *get_ambiguities(const SymOpList *source, const SymOpList *target)
int k;
for ( k=i+1; k<n_src; k++ ) {
- if ( check_mult(&src_reordered->ops[k],
- &src_reordered->ops[i],
- &target->ops[j]) )
+ if ( check_mult(src_reordered->ops[k],
+ src_reordered->ops[i],
+ tgt_reordered->ops[j]) )
{
used->mask[k] = 0;
}
@@ -1566,7 +1533,7 @@ SymOpList *get_ambiguities(const SymOpList *source, const SymOpList *target)
twins = new_symoplist();
for ( i=0; i<n_src; i++ ) {
if ( used->mask[i] == 0 ) continue;
- if ( determinant(&src_reordered->ops[i]) < 0 ) {
+ if ( intmat_det(src_reordered->ops[i]) < 0 ) {
/* A mirror or inversion turned up in the list.
* That means that no pure rotational ambiguity can
* account for this subgroup relationship. */
@@ -1575,11 +1542,12 @@ SymOpList *get_ambiguities(const SymOpList *source, const SymOpList *target)
free_symoplist(src_reordered);
return NULL;
}
- add_copied_op(twins, &src_reordered->ops[i]);
+ add_symop(twins, intmat_copy(src_reordered->ops[i]));
}
free_symopmask(used);
free_symoplist(src_reordered);
+ free_symoplist(tgt_reordered);
name = malloc(64);
snprintf(name, 63, "%s -> %s", symmetry_name(source),
@@ -1601,7 +1569,7 @@ static void add_chars(char *t, const char *s, int max_len)
}
-static char *get_matrix_name(signed int *v)
+static char *get_matrix_name(const IntegerMatrix *m, int row)
{
char *text;
const int max_len = 9;
@@ -1613,17 +1581,21 @@ static char *get_matrix_name(signed int *v)
for ( i=0; i<3; i++ ) {
- if ( v[i] == 0 ) continue;
+ signed int v;
+
+ v = intmat_get(m, row, i);
+
+ if ( v == 0 ) continue;
- if ( v[i]<0 ) {
+ if ( v < 0 ) {
add_chars(text, "-", max_len);
} else {
if ( printed ) add_chars(text, "+", max_len);
}
- if ( abs(v[i])>1 ) {
+ if ( abs(v) > 1 ) {
char num[3];
- snprintf(num, 2, "%i", abs(v[i]));
+ snprintf(num, 2, "%i", abs(v));
add_chars(text, num, max_len);
}
@@ -1643,14 +1615,14 @@ static char *get_matrix_name(signed int *v)
}
-static char *name_equiv(const struct sym_op *op)
+static char *name_equiv(const IntegerMatrix *op)
{
char *h, *k, *l;
char *name;
- h = get_matrix_name(op->h);
- k = get_matrix_name(op->k);
- l = get_matrix_name(op->l);
+ h = get_matrix_name(op, 0);
+ k = get_matrix_name(op, 1);
+ l = get_matrix_name(op, 2);
name = malloc(32);
if ( strlen(h)+strlen(k)+strlen(l) == 3 ) {
@@ -1658,9 +1630,6 @@ static char *name_equiv(const struct sym_op *op)
} else {
snprintf(name, 31, "%s,%s,%s", h, k, l);
}
- free(h);
- free(k);
- free(l);
return name;
}
@@ -1683,7 +1652,7 @@ void describe_symmetry(const SymOpList *s)
for ( i=0; i<n; i++ ) {
size_t len;
- char *name = name_equiv(&s->ops[i]);
+ char *name = name_equiv(s->ops[i]);
len = strlen(name);
if ( len > max_len ) max_len = len;
free(name);
@@ -1695,7 +1664,7 @@ void describe_symmetry(const SymOpList *s)
char *name;
size_t m, j;
- name = name_equiv(&s->ops[i]);
+ name = name_equiv(s->ops[i]);
m = max_len - strlen(name) + 3;
STATUS("%s", name);
@@ -1721,21 +1690,3 @@ const char *symmetry_name(const SymOpList *ops)
return ops->name;
}
-
-/**
- * add_op_intmat:
- * @s: A %SymOpList
- * @m: An %IntegerMatrix
- *
- * Adds @m to the @s. Operations are NOT cross-multiplied, i.e. the result
- * might not be a point group.
- */
-
-void add_op_intmat(SymOpList *s, const IntegerMatrix *m)
-{
- add_symop(s,
- v(intmat_get(m, 0, 0), intmat_get(m, 0, 1), 0, intmat_get(m, 0, 2)),
- v(intmat_get(m, 1, 0), intmat_get(m, 1, 1), 0, intmat_get(m, 1, 2)),
- v(intmat_get(m, 2, 0), intmat_get(m, 2, 1), 0, intmat_get(m, 2, 2)),
- 1);
-}