1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! 整数算术与晶体学对称操作的组合规则。
//!
//! 提供对称操作(3x3 整数矩阵 + 平移向量)的等价性判断,以及
//! 算术晶体类映射表(将空间群编号映射到点群对称性)。
/// 算术晶体类别映射表 (索引对应空间群编号 0-230)
/// 优化:使用 u8 节省内存,因为最大值为 73
static ARITHMETIC_CRYSTAL_CLASSES: [u8; 231] = [
0, 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8, 7, 7, 8, 9, 9, 9, 9, 10, 10, 11, 12, 12, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 14, 14, 14, 15, 15, 15, 15, 16, 16, 17, 17, 17, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 20, 20, 21, 21, 21, 21, 22, 22,
22, 22, 23, 23, 24, 25, 26, 26, 26, 26, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 30, 30,
30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 35, 35, 36, 36,
36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 39, 40, 41,
42, 43, 42, 43, 42, 43, 44, 45, 46, 45, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 51, 51, 51,
51, 52, 53, 53, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 57, 57, 56, 56, 58, 58, 58, 58, 59, 60,
61, 59, 61, 62, 62, 63, 63, 64, 62, 64, 65, 65, 66, 66, 67, 65, 65, 67, 68, 69, 70, 68, 69, 70,
71, 71, 71, 71, 72, 72, 72, 72, 73, 73,
];
/// 算术晶体类别符号表
/// 注意:这里的字符串已经包含了尾部空格,我们在返回时切片即可
static ARITHMETIC_CRYSTAL_CLASS_SYMBOLS: [&str; 74] = [
" ", /* 0 */
"1P ", /* 1 */
"-1P ", /* 2 */
"2P ", /* 3 */
"2C ", /* 4 */
"mP ", /* 5 */
"mC ", /* 6 */
"2/mP ", /* 7 */
"2/mC ", /* 8 */
"222P ", /* 9 */
"222C ", /* 10 */
"222F ", /* 11 */
"222I ", /* 12 */
"mm2P ", /* 13 */
"mm2C ", /* 14 */
"2mmC ", /* 15 */
"mm2F ", /* 16 */
"mm2I ", /* 17 */
"mmmP ", /* 18 */
"mmmC ", /* 19 */
"mmmF ", /* 20 */
"mmmI ", /* 21 */
"4P ", /* 22 */
"4I ", /* 23 */
"-4P ", /* 24 */
"-4I ", /* 25 */
"4/mP ", /* 26 */
"4/mI ", /* 27 */
"422P ", /* 28 */
"422I ", /* 29 */
"4mmP ", /* 30 */
"4mmI ", /* 31 */
"-42mP ", /* 32 */
"-4m2P ", /* 33 */
"-4m2I ", /* 34 */
"-42mI ", /* 35 */
"4/mmmP", /* 36 */
"4/mmmI", /* 37 */
"3P ", /* 38 */
"3R ", /* 39 */
"-3P ", /* 40 */
"-3R ", /* 41 */
"312P ", /* 42 */
"321P ", /* 43 */
"32R ", /* 44 */
"3m1P ", /* 45 */
"31mP ", /* 46 */
"3mR ", /* 47 */
"-31mP ", /* 48 */
"-3m1P ", /* 49 */
"-3mR ", /* 50 */
"6P ", /* 51 */
"-6P ", /* 52 */
"6/mP ", /* 53 */
"622P ", /* 54 */
"6mmP ", /* 55 */
"-62mP ", /* 56 */
"-6m2P ", /* 57 */
"6/mmmP", /* 58 */
"23P ", /* 59 */
"23F ", /* 60 */
"23I ", /* 61 */
"m-3P ", /* 62 */
"m-3F ", /* 63 */
"m-3I ", /* 64 */
"432P ", /* 65 */
"432F ", /* 66 */
"432I ", /* 67 */
"-43mP ", /* 68 */
"-43mF ", /* 69 */
"-43mI ", /* 70 */
"m-3mP ", /* 71 */
"m-3mF ", /* 72 */
"m-3mI ", /* 73 */
];
/// 获取算术晶体类别符号
///
/// # Arguments
/// * `spgroup_number`: 空间群编号 (1-230)
///
/// # Returns
/// * `Option<(u8, &'static str)>`: 如果输入有效,返回 (算术类别编号, 符号切片);否则返回 None。
/// 使用 Option 是比返回 (0, "") 更 Rust 的做法。
pub fn arth_get_symbol(spgroup_number: i32) -> Option<(u8, &'static str)> {
// 使用 get 进行安全的边界检查
// spgroup_number 是 1-based,所以需要减 1 才能对应 0-based 索引吗?
// 不,数组大小是 231,索引 0 是占位符,索引 1 对应空间群 1。
// 所以直接用 spgroup_number 作为索引。
let arth_number = *ARITHMETIC_CRYSTAL_CLASSES.get(spgroup_number as usize)?;
if arth_number == 0 {
return None;
}
// 获取原始字符串
let symbol_raw = ARITHMETIC_CRYSTAL_CLASS_SYMBOLS.get(arth_number as usize)?;
// 使用 trim_end() 返回一个 slice,不进行内存分配
// 生命周期为 'static,因为源数据是 static 的
let symbol = symbol_raw.trim_end();
Some((arth_number, symbol))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_arth_get_symbol() {
// Test case 1: Space group 1 (P1) -> Arithmetic class 1 (1P)
let result = arth_get_symbol(1);
assert_eq!(result, Some((1, "1P")));
// Test case 2: Space group 225 (Fm-3m) -> Arithmetic class 72 (m-3mF)
let result = arth_get_symbol(225);
assert_eq!(result, Some((72, "m-3mF")));
// Test case 3: Invalid input
assert_eq!(arth_get_symbol(0), None);
assert_eq!(arth_get_symbol(231), None);
assert_eq!(arth_get_symbol(-5), None);
}
}