1 /* Copyright (C) 2010 Atsushi Togo */
2 /* All rights reserved. */
3 
4 /* This file is part of spglib. */
5 
6 /* Redistribution and use in source and binary forms, with or without */
7 /* modification, are permitted provided that the following conditions */
8 /* are met: */
9 
10 /* * Redistributions of source code must retain the above copyright */
11 /*   notice, this list of conditions and the following disclaimer. */
12 
13 /* * Redistributions in binary form must reproduce the above copyright */
14 /*   notice, this list of conditions and the following disclaimer in */
15 /*   the documentation and/or other materials provided with the */
16 /*   distribution. */
17 
18 /* * Neither the name of the spglib project nor the names of its */
19 /*   contributors may be used to endorse or promote products derived */
20 /*   from this software without specific prior written permission. */
21 
22 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
23 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
24 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
25 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */
26 /* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */
27 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */
28 /* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
29 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */
30 /* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */
31 /* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */
32 /* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
33 /* POSSIBILITY OF SUCH DAMAGE. */
34 
35 #include <stdio.h>
36 #include "debug.h"
37 #include "hall_symbol.h"
38 #include "spg_database.h"
39 #include "spacegroup.h"
40 #include "symmetry.h"
41 #include "mathfunc.h"
42 
43 static int M_bcc[3][3] = {
44   { 0, 1, 1 },
45   { 1, 0, 1 },
46   { 1, 1, 0 },
47 };
48 static int M_fcc[3][3] = {
49   {-1, 1, 1 },
50   { 1,-1, 1 },
51   { 1, 1,-1 },
52 };
53 static int M_ac[3][3] = {
54   { 1, 0, 0 },
55   { 0, 1, 1 },
56   { 0,-1, 1 },
57 };
58 static int M_bc[3][3] = {
59   { 1, 0, 1 },
60   { 0, 1, 0 },
61   {-1, 0, 1 },
62 };
63 static int M_cc[3][3] = {
64   { 1,-1, 0 },
65   { 1, 1, 0 },
66   { 0, 0, 1 },
67 };
68 static int M_rc[3][3] = {
69   { 1, 0, 1 },
70   {-1, 1, 1 },
71   { 0,-1, 1 },
72 };
73 
74 static double M_bcc_inv[3][3] = {
75   {-0.5, 0.5, 0.5},
76   { 0.5,-0.5, 0.5},
77   { 0.5, 0.5,-0.5},
78 };
79 static double M_fcc_inv[3][3] = {
80   { 0.0, 0.5, 0.5},
81   { 0.5, 0.0, 0.5},
82   { 0.5, 0.5, 0.0},
83 };
84 static double M_ac_inv[3][3] = {
85   { 1.0, 0.0, 0.0},
86   { 0.0, 0.5,-0.5},
87   { 0.0, 0.5, 0.5},
88 };
89 static double M_bc_inv[3][3] = {
90   { 0.5, 0.0,-0.5},
91   { 0.0, 1.0, 0.0},
92   { 0.5, 0.0, 0.5},
93 };
94 static double M_cc_inv[3][3] = {
95   { 0.5, 0.5, 0.0},
96   {-0.5, 0.5, 0.0},
97   { 0.0, 0.0, 1.0},
98 };
99 static double M_rc_inv[3][3] = {
100   { 2./3,-1./3,-1./3},
101   { 1./3, 1./3,-2./3},
102   { 1./3, 1./3, 1./3},
103 };
104 
105 /* See: R. W. Grosse-Kunstleve, Acta Cryst. (1999). A55, 383-395 */
106 /* */
107 /* S is the Smith normal form, S = U*M*V */
108 /* M = R - I, where R is virtical stack of generator rotation matrices */
109 /* and I is virtical stack of identity matrices. */
110 /* */
111 /* Origin shift is given by (V*S+*U)*dw where dw is translations */
112 /* corresponding to those obtained by symmetry finder and from */
113 /* International table. */
114 /* S+ is given by the operations of inversion of the diagonal elements */
115 /* and then transpose. */
116 
117 static double tricli_VSpU[][3][9] =
118 {
119   { /* 1 */
120     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
121     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
122     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
123   },
124   { /* 2 */
125     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
126     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
127     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
128   },
129 };
130 
131 static int tricli_generators[][3][9] =
132 {
133   { /* 1 */
134     {  1, 0, 0, 0, 1, 0, 0, 0, 1, },
135     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
136     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
137   },
138   { /* 2 */
139     {  1, 0, 0, 0, 1, 0, 0, 0, 1, },
140     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
141     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
142   },
143 };
144 
145 static double monocli_VSpU[][3][9] =
146 {
147   { /* 1 */
148     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
149     { 0, -1.0/2, 0,  0,  0,  0,  0,  0,  0, },
150     { 0, 0, -1.0/2,  0,  0,  0,  0,  0,  0, },
151   },
152   { /* 2 */
153     { -1.0/2, 0, 0,  0,  0,  0,  0,  0,  0, },
154     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
155     { 0, 0, -1.0/2,  0,  0,  0,  0,  0,  0, },
156   },
157   { /* 3 */
158     { -1.0/2, 0, 0,  0,  0,  0,  0,  0,  0, },
159     { 0, -1.0/2, 0,  0,  0,  0,  0,  0,  0, },
160     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
161   },
162   { /* 4 */
163     { -1.0/2, 0, 0,  0,  0,  0,  0,  0,  0, },
164     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
165     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
166   },
167   { /* 5 */
168     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
169     { 0, -1.0/2, 0,  0,  0,  0,  0,  0,  0, },
170     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
171   },
172   { /* 6 */
173     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
174     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
175     { 0, 0, -1.0/2,  0,  0,  0,  0,  0,  0, },
176   },
177   { /* 7 */
178     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
179     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
180     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
181   },
182   { /* 8 */
183     { -1.0/2, 0, 0, 0, 0, 0,  0,  0,  0, },
184     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
185     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
186   },
187   { /* 9 */
188     { -1.0/2, 0, 0, 0, 0, 0,  0,  0,  0, },
189     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
190     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
191   },
192 };
193 
194 static double monocli_A_VSpU[][3][9] =
195 {
196   { /* 1 */
197     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
198     { 0, -1.0/2, 0,  0,  0,  0,  0,  0,  0, },
199     { 0, 0, -1.0/2,  0,  0,  0,  0,  0,  0, },
200   },
201   { /* 2 */
202     { -1.0/2, 0, 0,  0,  0,  0,  0,  0,  0, },
203     { 0, -1, 0,  0,  0,  0,  0,  0,  0, },
204     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
205   },
206   { /* 3 */
207     { -1.0/2, 0, 0,  0,  0,  0,  0,  0,  0, },
208     { 0, -1, 0,  0,  0,  0,  0,  0,  0, },
209     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
210   },
211   { /* 4 */
212     { -1.0/2, 0, 0,  0,  0,  0,  0,  0,  0, },
213     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
214     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
215   },
216   { /* 5 */
217     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
218     { 0, -1, 0,  0,  0,  0,  0,  0,  0, },
219     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
220   },
221   { /* 6 */
222     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
223     { 0, -1, 0,  0,  0,  0,  0,  0,  0, },
224     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
225   },
226   { /* 7 */
227     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
228     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
229     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
230   },
231   { /* 8 */
232     { -1.0/2, 0, 0, 0, 0, 0,  0,  0,  0, },
233     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
234     { 0, -1, 0, 0, 1.0/2, 0,  0,  0,  0, },
235   },
236   { /* 9 */
237     { -1.0/2, 0, 0, 0, 0, 0,  0,  0,  0, },
238     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
239     { 0, 1, 0, 0, -1.0/2, 0,  0,  0,  0, },
240   },
241 };
242 
243 static double monocli_B_VSpU[][3][9] =
244 {
245   { /* 1 */
246     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
247     { 0, -1.0/2, 0,  0,  0,  0,  0,  0,  0, },
248     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
249   },
250   { /* 2 */
251     { -1.0/2, 0, 0,  0,  0,  0,  0,  0,  0, },
252     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
253     { 0, 0, -1.0/2,  0,  0,  0,  0,  0,  0, },
254   },
255   { /* 3 */
256     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
257     { 0, -1.0/2, 0,  0,  0,  0,  0,  0,  0, },
258     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
259   },
260   { /* 4 */
261     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
262     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
263     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
264   },
265   { /* 5 */
266     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
267     { 0, -1.0/2, 0,  0,  0,  0,  0,  0,  0, },
268     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
269   },
270   { /* 6 */
271     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
272     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
273     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
274   },
275   { /* 7 */
276     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
277     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
278     { -1, 0, 0, 1.0/2, 0, 0,  0,  0,  0, },
279   },
280   { /* 8 */
281     { -1.0/2, 0, 0, 0, 0, 0,  0,  0,  0, },
282     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
283     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
284   },
285   { /* 9 */
286     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
287     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
288     { 1, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
289   },
290 };
291 
292 static double monocli_C_VSpU[][3][9] =
293 {
294   { /* 1 */
295     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
296     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
297     { 0, 0, -1.0/2,  0,  0,  0,  0,  0,  0, },
298   },
299   { /* 2 */
300     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
301     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
302     { 0, 0, -1.0/2,  0,  0,  0,  0,  0,  0, },
303   },
304   { /* 3 */
305     { -1.0/2, 0, 0,  0,  0,  0,  0,  0,  0, },
306     { 0, -1.0/2, 0,  0,  0,  0,  0,  0,  0, },
307     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
308   },
309   { /* 4 */
310     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
311     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
312     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
313   },
314   { /* 5 */
315     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
316     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
317     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
318   },
319   { /* 6 */
320     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
321     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
322     { 0, 0, -1.0/2,  0,  0,  0,  0,  0,  0, },
323   },
324   { /* 7 */
325     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
326     { 1, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
327     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
328   },
329   { /* 8 */
330     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
331     { -1, 0, 0, 1.0/2, 0, 0,  0,  0,  0, },
332     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
333   },
334   { /* 9 */
335     { -1.0/2, 0, 0, 0, 0, 0,  0,  0,  0, },
336     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
337     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
338   },
339 };
340 
341 static double monocli_I_VSpU[][3][9] =
342 {
343   { /* 1 */
344     { -1.0/2, 0, 0,  0,  0,  0,  0,  0,  0, },
345     { 1.0/2, -1, 0,  0,  0,  0,  0,  0,  0, },
346     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
347   },
348   { /* 2 */
349     { -1, 1.0/2, 0,  0,  0,  0,  0,  0,  0, },
350     { 0, -1.0/2, 0,  0,  0,  0,  0,  0,  0, },
351     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
352   },
353   { /* 3 */
354     { -1, 0, 1.0/2,  0,  0,  0,  0,  0,  0, },
355     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
356     { 0, 0, -1.0/2,  0,  0,  0,  0,  0,  0, },
357   },
358   { /* 4 */
359     { 0, 1, 0,  0,  0,  0,  0,  0,  0, },
360     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
361     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
362   },
363   { /* 5 */
364     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
365     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
366     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
367   },
368   { /* 6 */
369     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
370     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
371     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
372   },
373   { /* 7 */
374     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
375     { 0, -1, 0, 1.0/2, 0, -1.0/2,  0,  0,  0, },
376     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
377   },
378   { /* 8 */
379     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
380     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
381     { 1, -1.0/2, 0, -1.0/2, 0, 0,  0,  0,  0, },
382   },
383   { /* 9 */
384     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
385     { 1, 0, -1.0/2, -1.0/2, 0, 0,  0,  0,  0, },
386     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
387   },
388 };
389 
390 static int monocli_generators[][3][9] =
391 {
392   { /* 1 */
393     {  1, 0, 0, 0, -1, 0, 0, 0, -1, },
394     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
395     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
396   },
397   { /* 2 */
398     {  -1, 0, 0, 0, 1, 0, 0, 0, -1, },
399     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
400     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
401   },
402   { /* 3 */
403     {  -1, 0, 0, 0, -1, 0, 0, 0, 1, },
404     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
405     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
406   },
407   { /* 4 */
408     {  -1, 0, 0, 0, 1, 0, 0, 0, 1, },
409     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
410     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
411   },
412   { /* 5 */
413     {  1, 0, 0, 0, -1, 0, 0, 0, 1, },
414     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
415     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
416   },
417   { /* 6 */
418     {  1, 0, 0, 0, 1, 0, 0, 0, -1, },
419     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
420     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
421   },
422   { /* 7 */
423     {  1, 0, 0, 0, -1, 0, 0, 0, -1, },
424     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
425     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
426   },
427   { /* 8 */
428     {  -1, 0, 0, 0, 1, 0, 0, 0, -1, },
429     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
430     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
431   },
432   { /* 9 */
433     {  -1, 0, 0, 0, -1, 0, 0, 0, 1, },
434     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
435     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
436   },
437 };
438 
439 static double ortho_VSpU[][3][9] =
440 {
441   { /* 1 */
442     { -1.0/2, 0, 0, 0, 0, 0,  0,  0,  0, },
443     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
444     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
445   },
446   { /* 2 */
447     { -1.0/2, 0, 0, 0, 0, 0,  0,  0,  0, },
448     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
449     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
450   },
451   { /* 3 */
452     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
453     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
454     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
455   },
456   { /* 4 */
457     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
458     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
459     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
460   },
461   { /* 5 */
462     { -1.0/2, 0, 0, 0, 0, 0, 0, 0, 0, },
463     { 0, 0, 0, 0, -1.0/2, 0, 0, 0, 0, },
464     { 0, 0, 0, 0, 0, -1.0/2, 0, 0, 0, },
465   },
466 };
467 
468 static double ortho_F_VSpU[][3][9] =
469 {
470   { /* 1 */
471     { 0, 1.0/2, 0, -1.0/4, -1.0/4, 0,  0,  0,  0, },
472     { 0, -1.0/2, 0, -1.0/4, -1.0/4, 0,  0,  0,  0, },
473     { 0, -1.0/2, 0, -1.0/4, 3.0/4, 0,  0,  0,  0, },
474   },
475   { /* 2 */
476     { 0, 1, 0, 0, -1, 0,  0,  0,  0, },
477     { 0, 0, 0, 0, -1, 0,  0,  0,  0, },
478     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
479   },
480   { /* 3 */
481     { 0, -1, 0, 0, 1, 0,  0,  0,  0, },
482     { 0, 0, 0, 0, -1, 0,  0,  0,  0, },
483     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
484   },
485   { /* 4 */
486     { 0, -1, 0, 0, 1, 0,  0,  0,  0, },
487     { 0, 0, 0, 0, -1, 0,  0,  0,  0, },
488     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
489   },
490   { /* 5 */
491     { 0, 1, 0, 0, 0, 0, 0, -1.0/2, 0, },
492     { 0, 0, 0, 0, 0, 0, 0, -1.0/2, 0, },
493     { 0, 0, 0, 0, 1, 0, 0, -1.0/2, 0, },
494   },
495 };
496 
497 static double ortho_I_VSpU[][3][9] =
498 {
499   { /* 1 */
500     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
501     { 1.0/2, -1.0/2, 0, -1.0/2, 0, 0,  0,  0,  0, },
502     { -1.0/2, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
503   },
504   { /* 2 */
505     { -1.0/2, 0, 0, 0, 1.0/2, 0,  0,  0,  0, },
506     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
507     { -1.0/2, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
508   },
509   { /* 3 */
510     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
511     { 0, -1, 0, 1.0/2, 0, 0,  0,  0,  0, },
512     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
513   },
514   { /* 4 */
515     { -1.0/2, 0, 0, 0, 1.0/2, 0,  0,  0,  0, },
516     { -1.0/2, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
517     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
518   },
519   { /* 5 */
520     { 0, 0, 0, 0, 0, 0, -1.0/2, 0, 0, },
521     { 0, 0, -1.0/2, 0, -1, 0, 1.0/2, 0, 0, },
522     { 0, 0, -1.0/2, 0, 0, 0, 0, 0, 0, },
523   },
524 };
525 static double ortho_A_VSpU[][3][9] =
526 {
527   { /* 1 */
528     { -1.0/2, 0, 0, 0, 0, 0,  0,  0,  0, },
529     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
530     { 0, 1, 0, 0, -1.0/2, 0,  0,  0,  0, },
531   },
532   { /* 2 */
533     { -1.0/2, 0, 0, 0, 0, 0,  0,  0,  0, },
534     { 0, -1, 0, 0, 0, 0,  0,  0,  0, },
535     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
536   },
537   { /* 3 */
538     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
539     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
540     { 0, -1, 0, 0, 1.0/2, 0,  0,  0,  0, },
541   },
542   { /* 4 */
543     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
544     { 0, -1, 0, 0, 0, 0,  0,  0,  0, },
545     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
546   },
547   { /* 5 */
548     { -1.0/2, 0, 0, 0, 0, 0, 0, 0, 0, },
549     { 0, -1, 0, 0, 0, -1.0/2, 0, 0, 0, },
550     { 0, 0, 0, 0, 0, -1.0/2, 0, 0, 0, },
551   },
552 };
553 
554 static double ortho_B_VSpU[][3][9] =
555 {
556   { /* 1 */
557     { -1.0/2, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
558     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
559     { 1.0/2, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
560   },
561   { /* 2 */
562     { 0, 0, 0, -1, 0, 0,  0,  0,  0, },
563     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
564     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
565   },
566   { /* 3 */
567     { 0, 0, 0, -1, 0, 0,  0,  0,  0, },
568     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
569     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
570   },
571   { /* 4 */
572     { -1.0/2, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
573     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
574     { -1.0/2, 0, 0, 1.0/2, 0, 0,  0,  0,  0, },
575   },
576   { /* 5 */
577     { 0, 0, 0, 0, 0, 0, -1.0/2, 0, 0, },
578     { 0, 0, 0, 0, -1.0/2, 0, 0, 0, 0, },
579     { 0, 0, 0, -1, 0, 0, 1.0/2, 0, 0, },
580   },
581 };
582 
583 static double ortho_C_VSpU[][3][9] =
584 {
585   { /* 1 */
586     { -1.0/2, 0, 0, 0, 0, 0,  0,  0,  0, },
587     { -1.0/2, 0, 0, 1, 0, 0,  0,  0,  0, },
588     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
589   },
590   { /* 2 */
591     { -1.0/2, 0, 0, 0, 0, 0,  0,  0,  0, },
592     { 1.0/2, 0, 0, -1, 0, 0,  0,  0,  0, },
593     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
594   },
595   { /* 3 */
596     { 0, 0, 0, -1, 0, 0,  0,  0,  0, },
597     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
598     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
599   },
600   { /* 4 */
601     { 0, 0, 0, -1, 0, 0,  0,  0,  0, },
602     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
603     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
604   },
605   { /* 5 */
606     { 0, 0, 0, 0, 0, 0, -1.0/2, 0, 0, },
607     { 0, 0, 0, 1, 0, 0, -1.0/2, 0, 0, },
608     { 0, 0, 0, 0, 0, -1.0/2, 0, 0, 0, },
609   },
610 };
611 
612 static int ortho_generators[][3][9] =
613 {
614   { /* 1 */
615     {  -1, 0, 0, 0, -1, 0, 0, 0, 1, },
616     {  1, 0, 0, 0, -1, 0, 0, 0, -1, },
617     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
618   },
619   { /* 2 */
620     {  -1, 0, 0, 0, -1, 0, 0, 0, 1, },
621     {  -1, 0, 0, 0, 1, 0, 0, 0, 1, },
622     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
623   },
624   { /* 3 */
625     {  1, 0, 0, 0, 1, 0, 0, 0, -1, },
626     {  1, 0, 0, 0, -1, 0, 0, 0, -1, },
627     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
628   },
629   { /* 4 */
630     {  1, 0, 0, 0, 1, 0, 0, 0, -1, },
631     {  -1, 0, 0, 0, 1, 0, 0, 0, 1, },
632     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
633   },
634   { /* 5 */
635     {  -1, 0, 0, 0, -1, 0, 0, 0, 1, },
636     {  1, 0, 0, 0, -1, 0, 0, 0, -1, },
637     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
638   },
639 };
640 
641 static double tetra_VSpU[][3][9] =
642 {
643   { /* 1 */
644     { -1.0/2, 1.0/2, 0,  0,  0,  0,  0,  0,  0, },
645     { -1.0/2, -1.0/2, 0,  0,  0,  0,  0,  0,  0, },
646     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
647   },
648   { /* 2 */
649     { -1, 0, 0, 0, 1.0/2, 0,  0,  0,  0, },
650     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
651     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
652   },
653   { /* 3 */
654     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
655     { -1, 0, 0, 1.0/2, 0, 0,  0,  0,  0, },
656     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
657   },
658   { /* 4 */
659     { -1.0/2, -1.0/2, 0,  0,  0,  0,  0,  0,  0, },
660     { 1.0/2, -1.0/2, 0,  0,  0,  0,  0,  0,  0, },
661     { 0, 0, -1.0/2,  0,  0,  0,  0,  0,  0, },
662   },
663   { /* 5 */
664     { -1, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
665     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
666     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
667   },
668   { /* 6 */
669     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
670     { 1, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
671     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
672   },
673   { /* 7 */
674     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
675     { -1, 0, 0, 1.0/2, 0, 0,  0,  0,  0, },
676     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
677   },
678   { /* 8 */
679     { -1, 0, 0, 0, 1.0/2, 0, 0, 0, 0, },
680     { 0, 0, 0, 0, -1.0/2, 0, 0, 0, 0, },
681     { 0, 0, 0, 0, 0, -1.0/2, 0, 0, 0, },
682   },
683 };
684 
685 static double tetra_I_VSpU[][3][9] =
686 {
687   { /* 1 */
688     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
689     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
690     { 0, -1, 0,  0,  0,  0,  0,  0,  0, },
691   },
692   { /* 2 */
693     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
694     { 1, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
695     { 1, 0, -1, 0, 0, 0,  0,  0,  0, },
696   },
697   { /* 3 */
698     { -1, 0, 0, 0, 0, 0,  0,  0,  0, },
699     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
700     { -1, 0, 0, 0, -1, 0,  0,  0,  0, },
701   },
702   { /* 4 */
703     { -3.0/4, 1.0/4, 1.0/4,  0,  0,  0,  0,  0,  0, },
704     { -1.0/4, -1.0/4, -1.0/4,  0,  0,  0,  0,  0,  0, },
705     { -1.0/2, 1.0/2, -1.0/2,  0,  0,  0,  0,  0,  0, },
706   },
707   { /* 5 */
708     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
709     { -1, 0, 0, 1.0/2, 0, 0,  0,  0,  0, },
710     { 1, 0, -1, -1, 0, 0,  0,  0,  0, },
711   },
712   { /* 6 */
713     { -3.0/4, 1.0/4, 0, 0, 1.0/4, 0,  0,  0,  0, },
714     { -1.0/4, -1.0/4, 0, 0, -1.0/4, 0,  0,  0,  0, },
715     { -1.0/2, 1.0/2, 0, 0, -1.0/2, 0,  0,  0,  0, },
716   },
717   { /* 7 */
718     { 0, 2, 0, -1.0/2, 0, -1,  0,  0,  0, },
719     { 1, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
720     { 0, -1, 0, 0, 0, 0,  0,  0,  0, },
721   },
722   { /* 8 */
723     { -1, 0, 0, 0, -1, 0, 1.0/2, 0, -1.0/2, },
724     { 0, 0, 0, 0, -1, 0, 1.0/2, 0, -1.0/2, },
725     { 1, 0, 0, 0, 1, 0, -1, 0, 0, },
726   },
727 };
728 
729 static int tetra_generators[][3][9] =
730 {
731   { /* 1 */
732     {  0, -1, 0, 1, 0, 0, 0, 0, 1, },
733     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
734     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
735   },
736   { /* 2 */
737     {  0, -1, 0, 1, 0, 0, 0, 0, 1, },
738     {  1, 0, 0, 0, -1, 0, 0, 0, -1, },
739     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
740   },
741   { /* 3 */
742     {  0, -1, 0, 1, 0, 0, 0, 0, 1, },
743     {  -1, 0, 0, 0, 1, 0, 0, 0, 1, },
744     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
745   },
746   { /* 4 */
747     {  0, 1, 0, -1, 0, 0, 0, 0, -1, },
748     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
749     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
750   },
751   { /* 5 */
752     {  0, 1, 0, -1, 0, 0, 0, 0, -1, },
753     {  1, 0, 0, 0, -1, 0, 0, 0, -1, },
754     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
755   },
756   { /* 6 */
757     {  0, 1, 0, -1, 0, 0, 0, 0, -1, },
758     {  -1, 0, 0, 0, 1, 0, 0, 0, 1, },
759     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
760   },
761   { /* 7 */
762     {  0, -1, 0, 1, 0, 0, 0, 0, 1, },
763     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
764     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
765   },
766   { /* 8 */
767     {  0, -1, 0, 1, 0, 0, 0, 0, 1, },
768     {  1, 0, 0, 0, -1, 0, 0, 0, -1, },
769     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
770   },
771 };
772 
773 static double trigo_VSpU[][3][9] =
774 {
775   { /* 1 */
776     { -2.0/3, 1.0/3, 0,  0,  0,  0,  0,  0,  0, },
777     { -1.0/3, -1.0/3, 0,  0,  0,  0,  0,  0,  0, },
778     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
779   },
780   { /* 2 */
781     { 0, 1.0/3, 0, -2.0/3, 0, 0,  0,  0,  0, },
782     { 0, -1.0/3, 0, -1.0/3, 0, 0,  0,  0,  0, },
783     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
784   },
785   { /* 3 */
786     { 0, -1, 0, -2, 0, 0,  0,  0,  0, },
787     { 0, -1, 0, -1, 0, 0,  0,  0,  0, },
788     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
789   },
790   { /* 4 */
791     { 0, -1, 0, -2, 0, 0,  0,  0,  0, },
792     { 0, -1, 0, -1, 0, 0,  0,  0,  0, },
793     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
794   },
795   { /* 5 */
796     { 0, 1.0/3, 0, -2.0/3, 0, 0,  0,  0,  0, },
797     { 0, -1.0/3, 0, -1.0/3, 0, 0,  0,  0,  0, },
798     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
799   },
800   { /* 6 */
801     { 0, -1, 0,  0,  0,  0,  0,  0,  0, },
802     { 1, -1, 0,  0,  0,  0,  0,  0,  0, },
803     { 0, 0, -1.0/2,  0,  0,  0,  0,  0,  0, },
804   },
805   { /* 7 */
806     { 0, -1, 0, 0, 0, 0,  0,  0,  0, },
807     { 0, 1, 0, -1, 0, 0,  0,  0,  0, },
808     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
809   },
810   { /* 8 */
811     { 0, -1, 0, 0, 0, 0,  0,  0,  0, },
812     { 0, -1, 0, 1, 0, 0,  0,  0,  0, },
813     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
814   },
815   { /* 9 */
816     { 0, -1, 0, 0, 0, 0,  0,  0,  0, },
817     { 0, -1, 0, 1, 0, 0,  0,  0,  0, },
818     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
819   },
820   { /* 10 */
821     { 0, -1, 0, 0, 0, 0,  0,  0,  0, },
822     { 0, 1, 0, -1, 0, 0,  0,  0,  0, },
823     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
824   },
825   { /* 11 */
826     { -6, 3, 0, 4, 0, 0,  0,  0,  0, },
827     { -3, 1, 0, 2, 0, 0,  0,  0,  0, },
828     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
829   },
830   { /* 12 */
831     { 0, 1, 0, -2, 0, 0, 1, 0, 0, },
832     { 0, -1, 0, 1, 0, 0, -1, 0, 0, },
833     { 0, 0, 0, 0, 0, -1.0/2, 0, 0, 0, },
834   },
835   { /* 13 */
836     { 0, -1, 0, -2, 0, 0, 0, 0, 0, },
837     { 0, -1, 0, -1, 0, 0, 0, 0, 0, },
838     { 0, 0, 0, 0, 0, -1.0/2, 0, 0, 0, },
839   },
840 };
841 
842 static int trigo_generators[][3][9] =
843 {
844   { /* 1 */
845     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
846     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
847     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
848   },
849   { /* 2 */
850     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
851     {  0, -1, 0, -1, 0, 0, 0, 0, -1, },
852     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
853   },
854   { /* 3 */
855     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
856     {  0, 1, 0, 1, 0, 0, 0, 0, -1, },
857     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
858   },
859   { /* 4 */
860     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
861     {  0, 1, 0, 1, 0, 0, 0, 0, 1, },
862     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
863   },
864   { /* 5 */
865     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
866     {  0, -1, 0, -1, 0, 0, 0, 0, 1, },
867     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
868   },
869   { /* 6 */
870     {  0, 1, 0, -1, 1, 0, 0, 0, -1, },
871     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
872     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
873   },
874   { /* 7 */
875     {  0, 1, 0, -1, 1, 0, 0, 0, -1, },
876     {  0, -1, 0, -1, 0, 0, 0, 0, -1, },
877     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
878   },
879   { /* 8 */
880     {  0, 1, 0, -1, 1, 0, 0, 0, -1, },
881     {  0, 1, 0, 1, 0, 0, 0, 0, -1, },
882     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
883   },
884   { /* 9 */
885     {  0, 1, 0, -1, 1, 0, 0, 0, -1, },
886     {  0, 1, 0, 1, 0, 0, 0, 0, 1, },
887     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
888   },
889   { /* 10 */
890     {  0, 1, 0, -1, 1, 0, 0, 0, -1, },
891     {  0, -1, 0, -1, 0, 0, 0, 0, 1, },
892     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
893   },
894   { /* 11 */
895     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
896     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
897     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
898   },
899   { /* 12 */
900     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
901     {  0, -1, 0, -1, 0, 0, 0, 0, -1, },
902     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
903   },
904   { /* 13 */
905     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
906     {  0, 1, 0, 1, 0, 0, 0, 0, -1, },
907     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
908   },
909 };
910 
911 static double rhombo_h_VSpU[][3][9] =
912 {
913   { /* 1 */
914     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
915     { 0, 0, 1,  0,  0,  0,  0,  0,  0, },
916     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
917   },
918   { /* 2 */
919     { -1.0/2, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
920     { -1.0/2, -1, 0, -1.0/2, 0, 0,  0,  0,  0, },
921     { 1.0/2, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
922   },
923   { /* 3 */
924     { 0, 0, 0, -1, 0, 0,  0,  0,  0, },
925     { 0, -1, 0, -1, 0, 0,  0,  0,  0, },
926     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
927   },
928   { /* 4 */
929     { -1.0/2, -1.0/2, 1.0/2,  0,  0,  0,  0,  0,  0, },
930     { 1.0/2, -1.0/2, -1.0/2,  0,  0,  0,  0,  0,  0, },
931     { -1.0/2, 1.0/2, -1.0/2,  0,  0,  0,  0,  0,  0, },
932   },
933   { /* 5 */
934     { 0, -1, 0, 0, 1.0/2, 0,  0,  0,  0, },
935     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
936     { 0, 1, 0, -1, -1.0/2, 0,  0,  0,  0, },
937   },
938   { /* 6 */
939     { -1.0/2, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
940     { 1.0/2, -1, 0, 1.0/2, 0, 0,  0,  0,  0, },
941     { -1.0/2, 0, 0, 1.0/2, 0, 0,  0,  0,  0, },
942   },
943   { /* 7 */
944     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
945     { 1, 0, 1, -1.0/2, 0, 0,  0,  0,  0, },
946     { 1, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
947   },
948   { /* 8 */
949     { 0, 0, 0, 0, 0, 0, -1.0/2, 0, 0, },
950     { 0, -1, 0, 0, 0, 0, -1.0/2, 0, 0, },
951     { 0, 0, 0, -1, 0, 0, 1.0/2, 0, 0, },
952   },
953 };
954 
955 static int rhombo_h_generators[][3][9] =
956 {
957   { /* 1 */
958     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
959     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
960     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
961   },
962   { /* 2 */
963     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
964     {  0, 1, 0, 1, 0, 0, 0, 0, -1, },
965     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
966   },
967   { /* 3 */
968     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
969     {  0, -1, 0, -1, 0, 0, 0, 0, 1, },
970     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
971   },
972   { /* 4 */
973     {  0, 1, 0, -1, 1, 0, 0, 0, -1, },
974     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
975     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
976   },
977   { /* 5 */
978     {  0, 1, 0, -1, 1, 0, 0, 0, -1, },
979     {  0, 1, 0, 1, 0, 0, 0, 0, -1, },
980     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
981   },
982   { /* 6 */
983     {  0, 1, 0, -1, 1, 0, 0, 0, -1, },
984     {  0, -1, 0, -1, 0, 0, 0, 0, 1, },
985     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
986   },
987   { /* 7 */
988     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
989     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
990     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
991   },
992   { /* 8 */
993     {  0, -1, 0, 1, -1, 0, 0, 0, 1, },
994     {  0, 1, 0, 1, 0, 0, 0, 0, -1, },
995     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
996   },
997 };
998 
999 static double rhombo_p_VSpU[][3][9] =
1000 {
1001   { /* 1 */
1002     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
1003     { 0, 0, 1,  0,  0,  0,  0,  0,  0, },
1004     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
1005   },
1006   { /* 2 */
1007     { -1.0/2, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
1008     { -1.0/2, -1, 0, -1.0/2, 0, 0,  0,  0,  0, },
1009     { 1.0/2, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
1010   },
1011   { /* 3 */
1012     { 0, 0, 0, -1, 0, 0,  0,  0,  0, },
1013     { 0, -1, 0, -1, 0, 0,  0,  0,  0, },
1014     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
1015   },
1016   { /* 4 */
1017     { -1.0/2, -1.0/2, 1.0/2,  0,  0,  0,  0,  0,  0, },
1018     { 1.0/2, -1.0/2, -1.0/2,  0,  0,  0,  0,  0,  0, },
1019     { -1.0/2, 1.0/2, -1.0/2,  0,  0,  0,  0,  0,  0, },
1020   },
1021   { /* 5 */
1022     { 0, -1, 0, 0, 1.0/2, 0,  0,  0,  0, },
1023     { 0, 0, 0, 0, -1.0/2, 0,  0,  0,  0, },
1024     { 0, 1, 0, -1, -1.0/2, 0,  0,  0,  0, },
1025   },
1026   { /* 6 */
1027     { -1.0/2, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
1028     { 1.0/2, -1, 0, 1.0/2, 0, 0,  0,  0,  0, },
1029     { -1.0/2, 0, 0, 1.0/2, 0, 0,  0,  0,  0, },
1030   },
1031   { /* 7 */
1032     { 0, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
1033     { 1, 0, 1, -1.0/2, 0, 0,  0,  0,  0, },
1034     { 1, 0, 0, -1.0/2, 0, 0,  0,  0,  0, },
1035   },
1036   { /* 8 */
1037     { 0, 0, 0, 0, 0, 0, -1.0/2, 0, 0, },
1038     { 0, -1, 0, 0, 0, 0, -1.0/2, 0, 0, },
1039     { 0, 0, 0, -1, 0, 0, 1.0/2, 0, 0, },
1040   },
1041 };
1042 
1043 static int rhombo_p_generators[][3][9] =
1044 {
1045   { /* 1 */
1046     {  0, 0, 1, 1, 0, 0, 0, 1, 0, },
1047     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1048     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1049   },
1050   { /* 2 */
1051     {  0, 0, 1, 1, 0, 0, 0, 1, 0, },
1052     {  0, 0, -1, 0, -1, 0, -1, 0, 0, },
1053     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1054   },
1055   { /* 3 */
1056     {  0, 0, 1, 1, 0, 0, 0, 1, 0, },
1057     {  0, 0, 1, 0, 1, 0, 1, 0, 0, },
1058     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1059   },
1060   { /* 4 */
1061     {  0, 0, -1, -1, 0, 0, 0, -1, 0, },
1062     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1063     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1064   },
1065   { /* 5 */
1066     {  0, 0, -1, -1, 0, 0, 0, -1, 0, },
1067     {  0, 0, -1, 0, -1, 0, -1, 0, 0, },
1068     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1069   },
1070   { /* 6 */
1071     {  0, 0, -1, -1, 0, 0, 0, -1, 0, },
1072     {  0, 0, 1, 0, 1, 0, 1, 0, 0, },
1073     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1074   },
1075   { /* 7 */
1076     {  0, 0, 1, 1, 0, 0, 0, 1, 0, },
1077     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
1078     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1079   },
1080   { /* 8 */
1081     {  0, 0, 1, 1, 0, 0, 0, 1, 0, },
1082     {  0, 0, -1, 0, -1, 0, -1, 0, 0, },
1083     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
1084   },
1085 };
1086 
1087 static double hexa_VSpU[][3][9] =
1088 {
1089   { /* 1 */
1090     { -1, 1, 0,  0,  0,  0,  0,  0,  0, },
1091     { -1, 0, 0,  0,  0,  0,  0,  0,  0, },
1092     { 0, 0, 0,  0,  0,  0,  0,  0,  0, },
1093   },
1094   { /* 2 */
1095     { 1, 0, 0, -1, 0, 0,  0,  0,  0, },
1096     { -1, 0, 0, 0, 0, 0,  0,  0,  0, },
1097     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
1098   },
1099   { /* 3 */
1100     { -1, 0, 0, -1, 0, 0,  0,  0,  0, },
1101     { -1, 0, 0, 0, 0, 0,  0,  0,  0, },
1102     { 0, 0, 0, 0, 0, 0,  0,  0,  0, },
1103   },
1104   { /* 4 */
1105     { -1.0/3, -1.0/3, 0,  0,  0,  0,  0,  0,  0, },
1106     { 1.0/3, -2.0/3, 0,  0,  0,  0,  0,  0,  0, },
1107     { 0, 0, -1.0/2,  0,  0,  0,  0,  0,  0, },
1108   },
1109   { /* 5 */
1110     { -1.0/3, 0, 0, -1.0/3, 0, 0,  0,  0,  0, },
1111     { 1.0/3, 0, 0, -2.0/3, 0, 0,  0,  0,  0, },
1112     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
1113   },
1114   { /* 6 */
1115     { -1, 0, 0, 1, 0, 0,  0,  0,  0, },
1116     { -1, 0, 0, 2, 0, 0,  0,  0,  0, },
1117     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
1118   },
1119   { /* 7 */
1120     { -1, 1, 0, 0, 0, 0,  0,  0,  0, },
1121     { -1, 0, 0, 0, 0, 0,  0,  0,  0, },
1122     { 0, 0, 0, 0, 0, -1.0/2,  0,  0,  0, },
1123   },
1124   { /* 8 */
1125     { 1, 0, 0, -1, 0, 0, 0, 0, 0, },
1126     { -1, 0, 0, 0, 0, 0, 0, 0, 0, },
1127     { 0, 0, 0, 0, 0, -1.0/2, 0, 0, 0, },
1128   },
1129 };
1130 
1131 static int hexa_generators[][3][9] =
1132 {
1133   { /* 1 */
1134     {  1, -1, 0, 1, 0, 0, 0, 0, 1, },
1135     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1136     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1137   },
1138   { /* 2 */
1139     {  1, -1, 0, 1, 0, 0, 0, 0, 1, },
1140     {  0, -1, 0, -1, 0, 0, 0, 0, -1, },
1141     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1142   },
1143   { /* 3 */
1144     {  1, -1, 0, 1, 0, 0, 0, 0, 1, },
1145     {  0, 1, 0, 1, 0, 0, 0, 0, 1, },
1146     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1147   },
1148   { /* 4 */
1149     {  -1, 1, 0, -1, 0, 0, 0, 0, -1, },
1150     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1151     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1152   },
1153   { /* 5 */
1154     {  -1, 1, 0, -1, 0, 0, 0, 0, -1, },
1155     {  0, -1, 0, -1, 0, 0, 0, 0, -1, },
1156     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1157   },
1158   { /* 6 */
1159     {  -1, 1, 0, -1, 0, 0, 0, 0, -1, },
1160     {  0, 1, 0, 1, 0, 0, 0, 0, 1, },
1161     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1162   },
1163   { /* 7 */
1164     {  1, -1, 0, 1, 0, 0, 0, 0, 1, },
1165     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
1166     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1167   },
1168   { /* 8 */
1169     {  1, -1, 0, 1, 0, 0, 0, 0, 1, },
1170     {  0, -1, 0, -1, 0, 0, 0, 0, -1, },
1171     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
1172   },
1173 };
1174 
1175 static double cubic_VSpU[][3][9] =
1176 {
1177   { /* 1 */
1178     { -1.0/2, 1.0/2, 0, 0, 0, 0,  0,  0,  0, },
1179     { -1.0/2, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
1180     { -1.0/2, 1.0/2, 0, 1, 0, 0,  0,  0,  0, },
1181   },
1182   { /* 2 */
1183     { -1.0/2, 1.0/2, 0, 0, 0, 0,  0,  0,  0, },
1184     { -1.0/2, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
1185     { 1.0/2, -1.0/2, 0, -1, 0, 0,  0,  0,  0, },
1186   },
1187   { /* 3 */
1188     { 0, -1.0/2, 0, -1, 0, -1,  0,  0,  0, },
1189     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
1190     { 0, -1.0/2, 0, 0, 0, -1,  0,  0,  0, },
1191   },
1192   { /* 4 */
1193     { 0, -1.0/2, 0, -1, 0, 1,  0,  0,  0, },
1194     { 0, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
1195     { 0, 1.0/2, 0, 0, 0, -1,  0,  0,  0, },
1196   },
1197   { /* 5 */
1198     { -1.0/2, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
1199     { 1.0/2, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
1200     { -1.0/2, -1.0/2, 0, 1, 0, 0,  0,  0,  0, },
1201   },
1202   { /* 6 */
1203     { -1.0/2, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
1204     { 1.0/2, -1.0/2, 0, 0, 0, 0,  0,  0,  0, },
1205     { 1.0/2, 1.0/2, 0, -1, 0, 0,  0,  0,  0, },
1206   },
1207   { /* 7 */
1208     { 0, 0, -1.0/2, -1, 0, 0,  0,  0,  0, },
1209     { 0, 0, -1.0/2, 0, 0, 1,  0,  0,  0, },
1210     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
1211   },
1212   { /* 8 */
1213     { 0, 0, 1.0/2, -1, 0, 0,  0,  0,  0, },
1214     { 0, 0, 1.0/2, 0, 0, -1,  0,  0,  0, },
1215     { 0, 0, -1.0/2, 0, 0, 0,  0,  0,  0, },
1216   },
1217   { /* 9 */
1218     { 0, 0, 0, 0, 0, 0, -1.0/2, 0, 0, },
1219     { 0, -1, 0, 0, 0, 0, -1.0/2, 0, 0, },
1220     { 0, 0, 0, 1, 0, 0, -1.0/2, 0, 0, },
1221   },
1222   { /* 10 */
1223     { 0, 0, 0, 0, 0, 0, -1.0/2, 0, 0, },
1224     { 0, 0, 0, 1, 0, 1, -1.0/2, 0, 0, },
1225     { 0, 0, 0, 1, 0, 0, -1.0/2, 0, 0, },
1226   },
1227 };
1228 
1229 static double cubic_F_VSpU[][3][9] =
1230 {
1231   { /* 1 */
1232     { 0, 0, -1.0/2, -1.0/2, 0, 0,  0,  0,  0, },
1233     { 0, -1, 1.0/2, -1.0/2, 0, 0,  0,  0,  0, },
1234     { 0, 0, -1.0/2, 1.0/2, 0, 0,  0,  0,  0, },
1235   },
1236   { /* 2 */
1237     { 0, 1.0/2, -1.0/2, 0, -1.0/2, 0,  0,  0,  0, },
1238     { 0, -1.0/2, 1.0/2, 0, -1.0/2, 0,  0,  0,  0, },
1239     { 0, -1.0/2, -1.0/2, 0, 1.0/2, 0,  0,  0,  0, },
1240   },
1241   { /* 3 */
1242     { 0, 1.0/4, -1.0/4, -1.0/2, 0, 0,  0,  0,  0, },
1243     { 0, -3.0/4, -1.0/4, -1.0/2, 0, 0,  0,  0,  0, },
1244     { 0, 1.0/4, -1.0/4, 1.0/2, 0, 0,  0,  0,  0, },
1245   },
1246   { /* 4 */
1247     { 0, 1.0/2, 0, 0, -1.0/2, 0,  0,  0,  0, },
1248     { 0, -1.0/2, 0, 0, -1.0/2, 0,  0,  0,  0, },
1249     { 0, -1.0/2, 0, -1, 1.0/2, 0,  0,  0,  0, },
1250   },
1251   { /* 5 */
1252     { -1.0/4, 1.0/4, 0, -1.0/2, 0, 0,  0,  0,  0, },
1253     { -1.0/4, -3.0/4, 0, 1.0/2, 0, 0,  0,  0,  0, },
1254     { -1.0/4, 1.0/4, 0, 1.0/2, 0, 0,  0,  0,  0, },
1255   },
1256   { /* 6 */
1257     { 0, 0, 1.0/2, -1.0/2, 0, 0,  0,  0,  0, },
1258     { 0, -1, -1.0/2, -1.0/2, 0, 0,  0,  0,  0, },
1259     { 0, 0, -1.0/2, -1.0/2, 0, 0,  0,  0,  0, },
1260   },
1261   { /* 7 */
1262     { 0, -1.0/2, 0, -1.0/2, 0, -1.0/2,  0,  0,  0, },
1263     { 0, -1.0/2, 0, 1.0/2, 0, 1.0/2,  0,  0,  0, },
1264     { 0, -1.0/2, 0, 1.0/2, 0, -1.0/2,  0,  0,  0, },
1265   },
1266   { /* 8 */
1267     { 0, 0, 1.0/2, -1.0/2, 0, 1.0/2,  0,  0,  0, },
1268     { 0, 0, 1.0/2, 1.0/2, 0, -1.0/2,  0,  0,  0, },
1269     { 0, 0, -1.0/2, -1.0/2, 0, -1.0/2,  0,  0,  0, },
1270   },
1271   { /* 9 */
1272     { 0, 0, 0, 0, 0, 0, -1.0/2, 0, 0, },
1273     { 0, -1, 0, -1, 0, 0, 1.0/2, 0, 0, },
1274     { 0, 0, 0, 1, 0, 0, -1.0/2, 0, 0, },
1275   },
1276   { /* 10 */
1277     { 0, 0, 0, 0, 0, 0, -1.0/2, 0, 0, },
1278     { 0, 0, -1, -2, 0, 0, 3.0/2, 0, 0, },
1279     { 0, 0, 0, 1, 0, 0, -1.0/2, 0, 0, },
1280   },
1281 };
1282 
1283 static double cubic_I_VSpU[][3][9] =
1284 {
1285   { /* 1 */
1286     { 0, -1, 0, -1, 0, 0,  0,  0,  0, },
1287     { 1, -1, 0, -1, 0, 0,  0,  0,  0, },
1288     { 0, -1, 0, 0, 0, 0,  0,  0,  0, },
1289   },
1290   { /* 2 */
1291     { -1, 0, 1, -1, 0, 0,  0,  0,  0, },
1292     { 0, 0, 1, -1, 0, 0,  0,  0,  0, },
1293     { 1, 0, -1, 0, 0, 0,  0,  0,  0, },
1294   },
1295   { /* 3 */
1296     { 1, 0, -1, -2, 0, -1,  0,  0,  0, },
1297     { 1, 0, -1, -1, 0, 0,  0,  0,  0, },
1298     { 1, 0, -1, -1, 0, -1,  0,  0,  0, },
1299   },
1300   { /* 4 */
1301     { -1, 0, 1, 0, 0, -1,  0,  0,  0, },
1302     { 3, 0, -1, -3, 0, 2,  0,  0,  0, },
1303     { -3, 0, 1, 3, 0, -3,  0,  0,  0, },
1304   },
1305   { /* 5 */
1306     { 1, 2, -5, -7, 0, 0,  0,  0,  0, },
1307     { 1, 1, -4, -5, 0, 0,  0,  0,  0, },
1308     { 0, 1, -2, -2, 0, 0,  0,  0,  0, },
1309   },
1310   { /* 6 */
1311     { -2, 1, 0, 1, 0, 0,  0,  0,  0, },
1312     { 1, -1, 0, -1, 0, 0,  0,  0,  0, },
1313     { 2, -1, 0, -2, 0, 0,  0,  0,  0, },
1314   },
1315   { /* 7 */
1316     { -1, 0, 0, 0, 0, -1,  0,  0,  0, },
1317     { -1, 0, 0, 1, 0, 0,  0,  0,  0, },
1318     { -1, 0, 0, 1, 0, -1,  0,  0,  0, },
1319   },
1320   { /* 8 */
1321     { 1, 0, 0, 0, -2, 1,  0,  0,  0, },
1322     { -1, 0, 0, 0, 1, -1,  0,  0,  0, },
1323     { 1, 0, 0, 0, -1, 0,  0,  0,  0, },
1324   },
1325   { /* 9 */
1326     { -2, -3, 0, -1, 0, 0, 1, -1, 1, },
1327     { -1, -3, 0, -1, 0, 0, 1, -1, 1, },
1328     { 0, -1, 0, 0, 0, 0, 0, 0, 0, },
1329   },
1330   { /* 10 */
1331     { -1, 0, 0, 0, 0, -1, 0, -1, 1, },
1332     { -1, 0, 0, 1, 0, 0, 0, -1, 1, },
1333     { -1, 0, 0, 1, 0, -1, 0, -1, 1, },
1334   },
1335 };
1336 
1337 static int cubic_generators[][3][9] =
1338 {
1339   { /* 1 */
1340     {  0, -1, 0, 1, 0, 0, 0, 0, 1, },
1341     {  0, 0, 1, 1, 0, 0, 0, 1, 0, },
1342     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1343   },
1344   { /* 2 */
1345     {  0, -1, 0, 1, 0, 0, 0, 0, 1, },
1346     {  0, 0, -1, -1, 0, 0, 0, -1, 0, },
1347     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1348   },
1349   { /* 3 */
1350     {  -1, 0, 0, 0, -1, 0, 0, 0, 1, },
1351     {  0, 0, 1, 1, 0, 0, 0, 1, 0, },
1352     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1353   },
1354   { /* 4 */
1355     {  -1, 0, 0, 0, -1, 0, 0, 0, 1, },
1356     {  0, 0, -1, -1, 0, 0, 0, -1, 0, },
1357     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1358   },
1359   { /* 5 */
1360     {  0, 1, 0, -1, 0, 0, 0, 0, -1, },
1361     {  0, 0, 1, 1, 0, 0, 0, 1, 0, },
1362     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1363   },
1364   { /* 6 */
1365     {  0, 1, 0, -1, 0, 0, 0, 0, -1, },
1366     {  0, 0, -1, -1, 0, 0, 0, -1, 0, },
1367     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1368   },
1369   { /* 7 */
1370     {  1, 0, 0, 0, 1, 0, 0, 0, -1, },
1371     {  0, 0, 1, 1, 0, 0, 0, 1, 0, },
1372     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1373   },
1374   { /* 8 */
1375     {  1, 0, 0, 0, 1, 0, 0, 0, -1, },
1376     {  0, 0, -1, -1, 0, 0, 0, -1, 0, },
1377     {   0,  0,  0,  0,  0,  0,  0,  0,  0, },
1378   },
1379   { /* 9 */
1380     {  0, -1, 0, 1, 0, 0, 0, 0, 1, },
1381     {  0, 0, 1, 1, 0, 0, 0, 1, 0, },
1382     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
1383   },
1384   { /* 10 */
1385     {  -1, 0, 0, 0, -1, 0, 0, 0, 1, },
1386     {  0, 0, 1, 1, 0, 0, 0, 1, 0, },
1387     {  -1, 0, 0, 0, -1, 0, 0, 0, -1, },
1388   },
1389 };
1390 
1391 
1392 static int find_hall_symbol(double origin_shift[3],
1393                             SPGCONST double bravais_lattice[3][3],
1394                             const int hall_number,
1395                             const Centering centering,
1396                             const Symmetry *symmetry,
1397                             const double symprec);
1398 static int is_hall_symbol(double shift[3],
1399                           const int hall_number,
1400                           SPGCONST double primitive_lattice[3][3],
1401                           const Symmetry *symmetry,
1402                           const Centering centering,
1403                           SPGCONST int generators[3][9],
1404                           SPGCONST double VSpU[3][9],
1405                           const double symprec);
1406 static int is_hall_symbol_cubic(double shift[3],
1407                                 const int hall_number,
1408                                 SPGCONST double primitive_lattice[3][3],
1409                                 const Symmetry *symmetry,
1410                                 const Centering centering,
1411                                 const double symprec);
1412 static int is_hall_symbol_hexa(double shift[3],
1413                                const int hall_number,
1414                                SPGCONST double primitive_lattice[3][3],
1415                                const Symmetry *symmetry,
1416                                const double symprec);
1417 static int is_hall_symbol_rhombo(double shift[3],
1418                                  const int hall_number,
1419                                  SPGCONST double primitive_lattice[3][3],
1420                                  const Symmetry *symmetry,
1421                                  const double symprec);
1422 static int is_hall_symbol_trigonal(double shift[3],
1423                                    const int hall_number,
1424                                    SPGCONST double primitive_lattice[3][3],
1425                                    const Symmetry *symmetry,
1426                                    const double symprec);
1427 static int is_hall_symbol_tetra(double shift[3],
1428                                 const int hall_number,
1429                                 SPGCONST double primitive_lattice[3][3],
1430                                 const Symmetry *symmetry,
1431                                 const Centering centering,
1432                                 const double symprec);
1433 static int is_hall_symbol_ortho(double shift[3],
1434                                 const int hall_number,
1435                                 SPGCONST double primitive_lattice[3][3],
1436                                 const Symmetry *symmetry,
1437                                 const Centering centering,
1438                                 const double symprec);
1439 static int is_hall_symbol_monocli(double shift[3],
1440                                   const int hall_number,
1441                                   SPGCONST double primitive_lattice[3][3],
1442                                   const Symmetry *symmetry,
1443                                   const Centering centering,
1444                                   const double symprec);
1445 static int is_hall_symbol_tricli(double shift[3],
1446                                  const int hall_number,
1447                                  SPGCONST double primitive_lattice[3][3],
1448                                  const Symmetry *symmetry,
1449                                  const double symprec);
1450 static int get_translations(double trans[3][3],
1451                             const Symmetry *symmetry,
1452                             SPGCONST int rot[3][3][3]);
1453 static void transform_translation(double trans_reduced[3],
1454                                   const Centering centering,
1455                                   const double trans[3]);
1456 static void transform_rotation(double rot_reduced[3][3],
1457                                const Centering centering,
1458                                SPGCONST int rot[3][3]);
1459 static int get_origin_shift(double shift[3],
1460                             const int hall_number,
1461                             SPGCONST int rot[3][3][3],
1462                             SPGCONST double trans[3][3],
1463                             const Centering centering,
1464                             SPGCONST double VSpU[3][9]);
1465 static void unpack_generators(int rot[3][3][3], int generators[3][9]);
1466 static int set_dw(double dw[3],
1467                   const int operation_index[2],
1468                   SPGCONST int rot[3][3],
1469                   const double trans[3],
1470                   const Centering centering);
1471 static int is_match_database(const int hall_number,
1472                              const double shift[3],
1473                              SPGCONST double primitive_lattice[3][3],
1474                              const Centering centering,
1475                              const Symmetry *symmetry,
1476                              const double symprec);
1477 
1478 
hal_match_hall_symbol_db(double origin_shift[3],SPGCONST double bravais_lattice[3][3],const int hall_number,const Centering centering,const Symmetry * symmetry,const double symprec)1479 int hal_match_hall_symbol_db(double origin_shift[3],
1480                              SPGCONST double bravais_lattice[3][3],
1481                              const int hall_number,
1482                              const Centering centering,
1483                              const Symmetry *symmetry,
1484                              const double symprec)
1485 {
1486   return find_hall_symbol(origin_shift,
1487                           bravais_lattice,
1488                           hall_number,
1489                           centering,
1490                           symmetry,
1491                           symprec);
1492 }
1493 
find_hall_symbol(double origin_shift[3],SPGCONST double bravais_lattice[3][3],const int hall_number,const Centering centering,const Symmetry * symmetry,const double symprec)1494 static int find_hall_symbol(double origin_shift[3],
1495                             SPGCONST double bravais_lattice[3][3],
1496                             const int hall_number,
1497                             const Centering centering,
1498                             const Symmetry *symmetry,
1499                             const double symprec)
1500 {
1501   double primitive_lattice[3][3];
1502 
1503   switch (centering) {
1504   case PRIMITIVE:
1505     mat_copy_matrix_d3(primitive_lattice, bravais_lattice);
1506     break;
1507   case BODY:
1508     mat_multiply_matrix_d3(primitive_lattice, bravais_lattice, M_bcc_inv);
1509     break;
1510   case FACE:
1511     mat_multiply_matrix_d3(primitive_lattice, bravais_lattice, M_fcc_inv);
1512     break;
1513   case A_FACE:
1514     mat_multiply_matrix_d3(primitive_lattice, bravais_lattice, M_ac_inv);
1515     break;
1516   case B_FACE:
1517     mat_multiply_matrix_d3(primitive_lattice, bravais_lattice, M_bc_inv);
1518     break;
1519   case C_FACE:
1520     mat_multiply_matrix_d3(primitive_lattice, bravais_lattice, M_cc_inv);
1521     break;
1522   case R_CENTER:
1523     mat_multiply_matrix_d3(primitive_lattice, bravais_lattice, M_rc_inv);
1524     break;
1525   default:
1526     break;
1527   }
1528 
1529   /* CUBIC IT: 195-230, Hall: 489-530 */
1530   if (489 <= hall_number && hall_number <= 530) {
1531     if (is_hall_symbol_cubic(origin_shift,
1532                              hall_number,
1533                              primitive_lattice,
1534                              symmetry,
1535                              centering,
1536                              symprec)) {goto found;}
1537     return 0;
1538   }
1539 
1540   /* HEXA, IT: 168-194, Hall: 462-488 */
1541   if (462 <= hall_number && hall_number <= 488) {
1542     if (is_hall_symbol_hexa(origin_shift,
1543                             hall_number,
1544                             primitive_lattice,
1545                             symmetry,
1546                             symprec)) {goto found;}
1547     return 0;
1548   }
1549 
1550   /* TRIGO, IT: 143-167, Hall: 430-461 */
1551   if (430 <= hall_number && hall_number <= 461) {
1552     if (hall_number == 433 ||
1553         hall_number == 434 ||
1554         hall_number == 436 ||
1555         hall_number == 437 ||
1556         hall_number == 444 ||
1557         hall_number == 445 ||
1558         hall_number == 450 ||
1559         hall_number == 451 ||
1560         hall_number == 452 ||
1561         hall_number == 453 ||
1562         hall_number == 458 ||
1563         hall_number == 459 ||
1564         hall_number == 460 ||
1565         hall_number == 461) {
1566       if (is_hall_symbol_rhombo(origin_shift,
1567                                 hall_number,
1568                                 primitive_lattice,
1569                                 symmetry,
1570                                 symprec)) {goto found;}
1571     } else {
1572       if (is_hall_symbol_trigonal(origin_shift,
1573                                   hall_number,
1574                                   primitive_lattice,
1575                                   symmetry,
1576                                   symprec)) {goto found;}
1577     }
1578     return 0;
1579   }
1580 
1581   /* TETRA, IT: 75-142, Hall: 349-429 */
1582   if (349 <= hall_number && hall_number <= 429) {
1583     if (is_hall_symbol_tetra(origin_shift,
1584                              hall_number,
1585                              primitive_lattice,
1586                              symmetry,
1587                              centering,
1588                              symprec)) {goto found;}
1589     return 0;
1590   }
1591 
1592   /* ORTHO, IT: 16-74, Hall: 108-348 */
1593   if (108 <= hall_number && hall_number <= 348) {
1594     if (is_hall_symbol_ortho(origin_shift,
1595                              hall_number,
1596                              primitive_lattice,
1597                              symmetry,
1598                              centering,
1599                              symprec)) {goto found;}
1600     return 0;
1601   }
1602 
1603   /* MONOCLI, IT: 3-15, Hall: 3-107 */
1604   if (3 <= hall_number && hall_number <= 107) {
1605     if (is_hall_symbol_monocli(origin_shift,
1606                                hall_number,
1607                                primitive_lattice,
1608                                symmetry,
1609                                centering,
1610                                symprec)) {goto found;}
1611     return 0;
1612   }
1613 
1614   /* TRICLI, IT: 1-2, Hall: 1-2 */
1615   if (1 <= hall_number && hall_number <= 2) {
1616     if (is_hall_symbol_tricli(origin_shift,
1617                               hall_number,
1618                               primitive_lattice,
1619                               symmetry,
1620                               symprec)) {goto found;}
1621     return 0;
1622   }
1623 
1624   return 0;
1625 
1626  found:
1627   switch (centering) {
1628   case PRIMITIVE:
1629     break;
1630   case BODY:
1631     mat_multiply_matrix_vector_d3(origin_shift, M_bcc_inv, origin_shift);
1632     break;
1633   case FACE:
1634     mat_multiply_matrix_vector_d3(origin_shift, M_fcc_inv, origin_shift);
1635     break;
1636   case A_FACE:
1637     mat_multiply_matrix_vector_d3(origin_shift, M_ac_inv, origin_shift);
1638     break;
1639   case B_FACE:
1640     mat_multiply_matrix_vector_d3(origin_shift, M_bc_inv, origin_shift);
1641     break;
1642   case C_FACE:
1643     mat_multiply_matrix_vector_d3(origin_shift, M_cc_inv, origin_shift);
1644     break;
1645   case R_CENTER:
1646     mat_multiply_matrix_vector_d3(origin_shift, M_rc_inv, origin_shift);
1647     break;
1648   default:
1649     break;
1650   }
1651   return 1;
1652 }
1653 
is_hall_symbol_cubic(double shift[3],const int hall_number,SPGCONST double primitive_lattice[3][3],const Symmetry * symmetry,const Centering centering,const double symprec)1654 static int is_hall_symbol_cubic(double shift[3],
1655                                 const int hall_number,
1656                                 SPGCONST double primitive_lattice[3][3],
1657                                 const Symmetry *symmetry,
1658                                 const Centering centering,
1659                                 const double symprec)
1660 {
1661   int i;
1662 
1663   for (i = 0; i < 10; i++) {
1664     if (centering == PRIMITIVE) {
1665       if (is_hall_symbol(shift,
1666                          hall_number,
1667                          primitive_lattice,
1668                          symmetry,
1669                          centering,
1670                          cubic_generators[i],
1671                          cubic_VSpU[i],
1672                          symprec)) {goto found;}
1673     }
1674 
1675     if (centering == BODY) {
1676       if (is_hall_symbol(shift,
1677                          hall_number,
1678                          primitive_lattice,
1679                          symmetry,
1680                          centering,
1681                          cubic_generators[i],
1682                          cubic_I_VSpU[i],
1683                          symprec)) {goto found;}
1684     }
1685 
1686     if (centering == FACE) {
1687       if (is_hall_symbol(shift,
1688                          hall_number,
1689                          primitive_lattice,
1690                          symmetry,
1691                          centering,
1692                          cubic_generators[i],
1693                          cubic_F_VSpU[i],
1694                          symprec)) {goto found;}
1695     }
1696   }
1697 
1698   return 0;
1699 
1700 found:
1701   return 1;
1702 }
1703 
is_hall_symbol_hexa(double shift[3],const int hall_number,SPGCONST double primitive_lattice[3][3],const Symmetry * symmetry,const double symprec)1704 static int is_hall_symbol_hexa(double shift[3],
1705                                const int hall_number,
1706                                SPGCONST double primitive_lattice[3][3],
1707                                const Symmetry *symmetry,
1708                                const double symprec)
1709 {
1710   int i;
1711 
1712   for (i = 0; i < 8; i++) {
1713     if (is_hall_symbol(shift,
1714                        hall_number,
1715                        primitive_lattice,
1716                        symmetry,
1717                        PRIMITIVE,
1718                        hexa_generators[i],
1719                        hexa_VSpU[i],
1720                        symprec)) {return 1;}
1721   }
1722 
1723   return 0;
1724 }
1725 
is_hall_symbol_trigonal(double shift[3],const int hall_number,SPGCONST double primitive_lattice[3][3],const Symmetry * symmetry,const double symprec)1726 static int is_hall_symbol_trigonal(double shift[3],
1727                                    const int hall_number,
1728                                    SPGCONST double primitive_lattice[3][3],
1729                                    const Symmetry *symmetry,
1730                                    const double symprec)
1731 {
1732   int i;
1733 
1734   for (i = 0; i < 13; i++) {
1735     if (is_hall_symbol(shift,
1736                        hall_number,
1737                        primitive_lattice,
1738                        symmetry,
1739                        PRIMITIVE,
1740                        trigo_generators[i],
1741                        trigo_VSpU[i],
1742                        symprec)) {return 1;}
1743   }
1744 
1745   return 0;
1746 }
1747 
is_hall_symbol_rhombo(double shift[3],const int hall_number,SPGCONST double primitive_lattice[3][3],const Symmetry * symmetry,const double symprec)1748 static int is_hall_symbol_rhombo(double shift[3],
1749                                  const int hall_number,
1750                                  SPGCONST double primitive_lattice[3][3],
1751                                  const Symmetry *symmetry,
1752                                  const double symprec)
1753 {
1754   int i;
1755 
1756   if (hall_number == 433 ||
1757       hall_number == 436 ||
1758       hall_number == 444 ||
1759       hall_number == 450 ||
1760       hall_number == 452 ||
1761       hall_number == 458 ||
1762       hall_number == 460) {
1763     /* hP */
1764     for (i = 0; i < 8; i++) {
1765       if (is_hall_symbol(shift,
1766                          hall_number,
1767                          primitive_lattice,
1768                          symmetry,
1769                          R_CENTER,
1770                          rhombo_h_generators[i],
1771                          rhombo_h_VSpU[i],
1772                          symprec)) {return 1;}
1773     }
1774   } else {
1775     /* hR */
1776     for (i = 0; i < 8; i++) {
1777       if (is_hall_symbol(shift,
1778                          hall_number,
1779                          primitive_lattice,
1780                          symmetry,
1781                          PRIMITIVE,
1782                          rhombo_p_generators[i],
1783                          rhombo_p_VSpU[i],
1784                          symprec)) {return 1;}
1785     }
1786   }
1787 
1788   return 0;
1789 }
1790 
is_hall_symbol_tetra(double shift[3],const int hall_number,SPGCONST double primitive_lattice[3][3],const Symmetry * symmetry,const Centering centering,const double symprec)1791 static int is_hall_symbol_tetra(double shift[3],
1792                                 const int hall_number,
1793                                 SPGCONST double primitive_lattice[3][3],
1794                                 const Symmetry *symmetry,
1795                                 const Centering centering,
1796                                 const double symprec)
1797 {
1798   int i;
1799 
1800   for (i = 0; i < 8; i++) {
1801     if (centering==PRIMITIVE) {
1802       if (is_hall_symbol(shift,
1803                          hall_number,
1804                          primitive_lattice,
1805                          symmetry,
1806                          centering,
1807                          tetra_generators[i],
1808                          tetra_VSpU[i],
1809                          symprec)) {return 1;}
1810     }
1811 
1812     if (centering==BODY) {
1813       if (is_hall_symbol(shift,
1814                          hall_number,
1815                          primitive_lattice,
1816                          symmetry,
1817                          centering,
1818                          tetra_generators[i],
1819                          tetra_I_VSpU[i],
1820                          symprec)) {return 1;}
1821     }
1822   }
1823 
1824   return 0;
1825 }
1826 
is_hall_symbol_ortho(double shift[3],const int hall_number,SPGCONST double primitive_lattice[3][3],const Symmetry * symmetry,const Centering centering,const double symprec)1827 static int is_hall_symbol_ortho(double shift[3],
1828                                 const int hall_number,
1829                                 SPGCONST double primitive_lattice[3][3],
1830                                 const Symmetry *symmetry,
1831                                 const Centering centering,
1832                                 const double symprec)
1833 {
1834   int i;
1835 
1836   for (i = 0; i < 5; i++) {
1837     if (centering == PRIMITIVE) {
1838       if (is_hall_symbol(shift,
1839                          hall_number,
1840                          primitive_lattice,
1841                          symmetry,
1842                          centering,
1843                          ortho_generators[i],
1844                          ortho_VSpU[i],
1845                          symprec)) {return 1;}
1846     }
1847 
1848     if (centering == BODY) {
1849       if (is_hall_symbol(shift,
1850                          hall_number,
1851                          primitive_lattice,
1852                          symmetry,
1853                          centering,
1854                          ortho_generators[i],
1855                          ortho_I_VSpU[i],
1856                          symprec)) {return 1;}
1857     }
1858 
1859     if (centering == FACE) {
1860       if (is_hall_symbol(shift,
1861                          hall_number,
1862                          primitive_lattice,
1863                          symmetry,
1864                          centering,
1865                          ortho_generators[i],
1866                          ortho_F_VSpU[i],
1867                          symprec)) {return 1;}
1868     }
1869 
1870     if (centering == A_FACE) {
1871       if (is_hall_symbol(shift,
1872                          hall_number,
1873                          primitive_lattice,
1874                          symmetry,
1875                          centering,
1876                          ortho_generators[i],
1877                          ortho_A_VSpU[i],
1878                          symprec)) {return 1;}
1879     }
1880 
1881     if (centering == B_FACE) {
1882       if (is_hall_symbol(shift,
1883                          hall_number,
1884                          primitive_lattice,
1885                          symmetry,
1886                          centering,
1887                          ortho_generators[i],
1888                          ortho_B_VSpU[i],
1889                          symprec)) {return 1;}
1890     }
1891 
1892     if (centering == C_FACE) {
1893       if (is_hall_symbol(shift,
1894                          hall_number,
1895                          primitive_lattice,
1896                          symmetry,
1897                          centering,
1898                          ortho_generators[i],
1899                          ortho_C_VSpU[i],
1900                          symprec)) {return 1;}
1901     }
1902   }
1903 
1904   return 0;
1905 }
1906 
is_hall_symbol_monocli(double shift[3],const int hall_number,SPGCONST double primitive_lattice[3][3],const Symmetry * symmetry,const Centering centering,const double symprec)1907 static int is_hall_symbol_monocli(double shift[3],
1908                                   const int hall_number,
1909                                   SPGCONST double primitive_lattice[3][3],
1910                                   const Symmetry *symmetry,
1911                                   const Centering centering,
1912                                   const double symprec)
1913 {
1914   int i;
1915 
1916   for (i = 0; i < 9; i++) {
1917     if (centering == PRIMITIVE) {
1918       if (is_hall_symbol(shift,
1919                          hall_number,
1920                          primitive_lattice,
1921                          symmetry,
1922                          centering,
1923                          monocli_generators[i],
1924                          monocli_VSpU[i],
1925                          symprec)) {return 1;}
1926     }
1927 
1928     if (centering == A_FACE) {
1929       if (is_hall_symbol(shift,
1930                          hall_number,
1931                          primitive_lattice,
1932                          symmetry,
1933                          centering,
1934                          monocli_generators[i],
1935                          monocli_A_VSpU[i],
1936                          symprec)) {return 1;}
1937     }
1938 
1939     if (centering == B_FACE) {
1940       if (is_hall_symbol(shift,
1941                          hall_number,
1942                          primitive_lattice,
1943                          symmetry,
1944                          centering,
1945                          monocli_generators[i],
1946                          monocli_B_VSpU[i],
1947                          symprec)) {return 1;}
1948     }
1949 
1950     if (centering == C_FACE) {
1951       if (is_hall_symbol(shift,
1952                          hall_number,
1953                          primitive_lattice,
1954                          symmetry,
1955                          centering,
1956                          monocli_generators[i],
1957                          monocli_C_VSpU[i],
1958                          symprec)) {return 1;}
1959     }
1960 
1961     if (centering == BODY) {
1962       if (is_hall_symbol(shift,
1963                          hall_number,
1964                          primitive_lattice,
1965                          symmetry,
1966                          centering,
1967                          monocli_generators[i],
1968                          monocli_I_VSpU[i],
1969                          symprec)) {return 1;}
1970     }
1971   }
1972 
1973   return 0;
1974 }
1975 
is_hall_symbol_tricli(double shift[3],const int hall_number,SPGCONST double primitive_lattice[3][3],const Symmetry * symmetry,const double symprec)1976 static int is_hall_symbol_tricli(double shift[3],
1977                                  const int hall_number,
1978                                  SPGCONST double primitive_lattice[3][3],
1979                                  const Symmetry *symmetry,
1980                                  const double symprec)
1981 {
1982   int i;
1983 
1984   for (i = 0; i < 2; i++) {
1985     if (is_hall_symbol(shift,
1986                        hall_number,
1987                        primitive_lattice,
1988                        symmetry,
1989                        PRIMITIVE,
1990                        tricli_generators[i],
1991                        tricli_VSpU[i],
1992                        symprec)) {return 1;}
1993   }
1994 
1995   return 0;
1996 }
1997 
unpack_generators(int rot[3][3][3],int generators[3][9])1998 static void unpack_generators(int rot[3][3][3], int generators[3][9])
1999 {
2000   int i, j, k;
2001   for (i = 0; i < 3; i++) {
2002     for (j = 0; j < 3; j++) {
2003       for (k = 0; k < 3; k++) {
2004         rot[i][j][k] = generators[i][j*3+k];
2005       }
2006     }
2007   }
2008 }
2009 
is_hall_symbol(double shift[3],const int hall_number,SPGCONST double primitive_lattice[3][3],const Symmetry * symmetry,const Centering centering,SPGCONST int generators[3][9],SPGCONST double VSpU[3][9],const double symprec)2010 static int is_hall_symbol(double shift[3],
2011                           const int hall_number,
2012                           SPGCONST double primitive_lattice[3][3],
2013                           const Symmetry *symmetry,
2014                           const Centering centering,
2015                           SPGCONST int generators[3][9],
2016                           SPGCONST double VSpU[3][9],
2017                           const double symprec)
2018 {
2019   int is_origin_shift;
2020   int operation_index[2];
2021   int rot[3][3][3];
2022   double trans[3][3];
2023 
2024   debug_print("[line %d, %s]\n", __LINE__, __FILE__);
2025   debug_print("primitive lattice\n");
2026   debug_print_matrix_d3(primitive_lattice);
2027 
2028   spgdb_get_operation_index(operation_index, hall_number);
2029 
2030   if (! (operation_index[0] == symmetry->size)) {
2031     goto not_found;
2032   }
2033 
2034   unpack_generators(rot, generators);
2035   if (get_translations(trans, symmetry, rot)) {
2036     is_origin_shift = get_origin_shift(shift,
2037                                        hall_number,
2038                                        rot,
2039                                        trans,
2040                                        centering,
2041                                        VSpU);
2042 
2043     if (is_origin_shift) {
2044       if (is_match_database(hall_number,
2045                             shift,
2046                             primitive_lattice,
2047                             centering,
2048                             symmetry,
2049                             symprec)) {goto found;}
2050     }
2051   } else {
2052     goto not_found;
2053   }
2054 
2055  not_found:
2056   return 0;
2057 
2058  found:
2059   debug_print("[line %d, %s]\n", __LINE__, __FILE__);
2060   debug_print("origin shift\n");
2061   debug_print_vector_d3(shift);
2062 
2063   return 1;
2064 }
2065 
get_translations(double trans[3][3],const Symmetry * symmetry,SPGCONST int rot[3][3][3])2066 static int get_translations(double trans[3][3],
2067                             const Symmetry *symmetry,
2068                             SPGCONST int rot[3][3][3])
2069 {
2070   int i, j;
2071   int is_found;
2072   static SPGCONST int zero[3][3] = { { 0, 0, 0 },
2073                                      { 0, 0, 0 },
2074                                      { 0, 0, 0 }, };
2075 
2076   for (i = 0; i < 3; i++) {
2077     for (j = 0; j < 3; j++) {
2078       trans[i][j] = 0;
2079     }
2080   }
2081 
2082   for (i = 0; i < 3; i++) {
2083     if (mat_check_identity_matrix_i3(rot[i], zero)) { continue; }
2084     is_found = 0;
2085     for (j = 0; j < symmetry->size; j++) {
2086       if (mat_check_identity_matrix_i3(symmetry->rot[j], rot[i])) {
2087         mat_copy_vector_d3(trans[i], symmetry->trans[j]);
2088         is_found = 1;
2089         break;
2090       }
2091     }
2092     if (! is_found) {
2093       goto not_found;
2094     }
2095   }
2096 
2097   return 1;
2098 
2099  not_found:
2100 
2101   return 0;
2102 }
2103 
transform_translation(double trans_reduced[3],const Centering centering,const double trans[3])2104 static void transform_translation(double trans_reduced[3],
2105                                   const Centering centering,
2106                                   const double trans[3])
2107 {
2108   int i;
2109 
2110   switch (centering) {
2111   case PRIMITIVE:
2112     mat_copy_vector_d3(trans_reduced, trans);
2113     break;
2114   case BODY:
2115     mat_multiply_matrix_vector_id3(trans_reduced, M_bcc, trans);
2116     break;
2117   case FACE:
2118     mat_multiply_matrix_vector_id3(trans_reduced, M_fcc, trans);
2119     break;
2120   case A_FACE:
2121     mat_multiply_matrix_vector_id3(trans_reduced, M_ac, trans);
2122     break;
2123   case B_FACE:
2124     mat_multiply_matrix_vector_id3(trans_reduced, M_bc, trans);
2125     break;
2126   case C_FACE:
2127     mat_multiply_matrix_vector_id3(trans_reduced, M_cc, trans);
2128     break;
2129   case R_CENTER:
2130     mat_multiply_matrix_vector_id3(trans_reduced, M_rc, trans);
2131     break;
2132   default:
2133     break;
2134   }
2135 
2136   for (i = 0; i < 3; i++) {
2137     trans_reduced[i] = mat_Dmod1(trans_reduced[i]);
2138   }
2139 }
2140 
transform_rotation(double rot_reduced[3][3],const Centering centering,SPGCONST int rot[3][3])2141 static void transform_rotation(double rot_reduced[3][3],
2142                                const Centering centering,
2143                                SPGCONST int rot[3][3])
2144 {
2145   mat_cast_matrix_3i_to_3d(rot_reduced, rot);
2146   if (centering != PRIMITIVE) {
2147     switch (centering) {
2148     case BODY:
2149       mat_get_similar_matrix_d3(rot_reduced, rot_reduced, M_bcc_inv, 0);
2150       break;
2151     case FACE:
2152       mat_get_similar_matrix_d3(rot_reduced, rot_reduced, M_fcc_inv, 0);
2153       break;
2154     case A_FACE:
2155       mat_get_similar_matrix_d3(rot_reduced, rot_reduced, M_ac_inv, 0);
2156       break;
2157     case B_FACE:
2158       mat_get_similar_matrix_d3(rot_reduced, rot_reduced, M_bc_inv, 0);
2159       break;
2160     case C_FACE:
2161       mat_get_similar_matrix_d3(rot_reduced, rot_reduced, M_cc_inv, 0);
2162       break;
2163     case R_CENTER:
2164       mat_get_similar_matrix_d3(rot_reduced, rot_reduced, M_rc_inv, 0);
2165       break;
2166     default:
2167       break;
2168     }
2169   }
2170 }
2171 
get_origin_shift(double shift[3],const int hall_number,SPGCONST int rot[3][3][3],SPGCONST double trans[3][3],const Centering centering,SPGCONST double VSpU[3][9])2172 static int get_origin_shift(double shift[3],
2173                             const int hall_number,
2174                             SPGCONST int rot[3][3][3],
2175                             SPGCONST double trans[3][3],
2176                             const Centering centering,
2177                             SPGCONST double VSpU[3][9])
2178 {
2179   int i, j;
2180   int operation_index[2];
2181   double dw[9], tmp_dw[3];
2182 
2183   spgdb_get_operation_index(operation_index, hall_number);
2184 
2185   /* The obtained dw is reduced to that of primitve cell by centerings. */
2186   for (i = 0; i < 3; i++) {
2187     /* Zero matrix is the sign to set dw 0 */
2188     if (mat_get_determinant_i3(rot[i]) == 0) {
2189       for (j = 0; j < 3; j++) {
2190         dw[i * 3 + j] = 0;
2191       }
2192     } else {
2193       if (set_dw(tmp_dw, operation_index, rot[i], trans[i], centering)) {
2194         for (j = 0; j < 3; j++) {
2195           dw[i * 3 + j] = tmp_dw[j];
2196         }
2197       } else {
2198         goto not_found;
2199       }
2200     }
2201   }
2202 
2203   /* VSpU*dw is given for the primitive cell if there is centering. */
2204   for (i = 0; i < 3; i++) {
2205     shift[i] = 0;
2206     for (j = 0; j < 9; j++) {
2207       shift[i] += VSpU[i][j] * dw[j];
2208     }
2209     shift[i] = mat_Dmod1(shift[i]);
2210   }
2211 
2212   return 1;
2213 
2214  not_found:
2215   return 0;
2216 }
2217 
set_dw(double dw[3],const int operation_index[2],SPGCONST int rot[3][3],const double trans[3],const Centering centering)2218 static int set_dw(double dw[3],
2219                   const int operation_index[2],
2220                   SPGCONST int rot[3][3],
2221                   const double trans[3],
2222                   const Centering centering)
2223 {
2224   int i, j;
2225   int rot_db[3][3];
2226   double trans_db[3], trans_prim[3], trans_db_prim[3];
2227 
2228   transform_translation(trans_prim, centering, trans);
2229   for (i = 0; i < operation_index[0]; i++) {
2230     spgdb_get_operation(rot_db, trans_db, operation_index[1] + i);
2231     transform_translation(trans_db_prim, centering, trans_db);
2232     if (mat_check_identity_matrix_i3(rot_db, rot)) {
2233       for (j = 0; j < 3; j++) {
2234         dw[j] = trans_prim[j] - trans_db_prim[j];
2235         dw[j] = mat_Dmod1(dw[j]);
2236       }
2237       goto found;
2238     }
2239   }
2240 
2241   /* Not found */
2242   return 0;
2243 
2244  found:
2245   return 1;
2246 }
2247 
is_match_database(const int hall_number,const double origin_shift[3],SPGCONST double primitive_lattice[3][3],const Centering centering,const Symmetry * symmetry,const double symprec)2248 static int is_match_database(const int hall_number,
2249                              const double origin_shift[3],
2250                              SPGCONST double primitive_lattice[3][3],
2251                              const Centering centering,
2252                              const Symmetry *symmetry,
2253                              const double symprec)
2254 {
2255   int i, j, k, is_found;
2256   int operation_index[2];
2257   int rot_db[3][3];
2258   int found_list[192];
2259   double trans_db[3], trans_db_prim[3], trans_prim[3], diff[3], shift_rot[3];
2260   double rot_prim[3][3];
2261 
2262   spgdb_get_operation_index(operation_index, hall_number);
2263 
2264   for (i = 0; i < symmetry->size; i++) {found_list[i] = 0;}
2265   for (i = 0; i < symmetry->size; i++) {
2266     is_found = 0;
2267     for (j = 0; j < operation_index[0]; j++) {
2268       spgdb_get_operation(rot_db, trans_db, operation_index[1] + j);
2269       if (mat_check_identity_matrix_i3(symmetry->rot[i], rot_db)) {
2270         transform_translation(trans_db_prim, centering, trans_db);
2271         transform_translation(trans_prim, centering, symmetry->trans[i]);
2272         transform_rotation(rot_prim, centering, rot_db);
2273         for (k = 0; k < 3; k++) {
2274           diff[k] = trans_prim[k] - trans_db_prim[k] + origin_shift[k];
2275         }
2276         mat_multiply_matrix_vector_d3(shift_rot, rot_prim, origin_shift);
2277         if (cel_is_overlap(diff, shift_rot, primitive_lattice, symprec)) {
2278           if (! found_list[j]) {
2279             found_list[j] = 1;
2280             is_found = 1;
2281             break;
2282           }
2283         }
2284       }
2285     }
2286 
2287     if (! is_found) {
2288       goto not_found;
2289     }
2290   }
2291 
2292   return 1;
2293 
2294  not_found:
2295   return 0;
2296 }
2297