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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
//! Blade indexing and grade utilities.
//!
//! This module provides functions for working with basis blade indices.
//! In this library, blades are indexed using their binary representation:
//! each bit indicates whether a particular basis vector is present.
//!
//! # Indexing Scheme
//!
//! For a basis blade, its index is a bitmask where bit `i` is set if
//! basis vector `e_i` is present. For example, in 3D:
//!
//! | Index | Binary | Blade |
//! |-------|--------|-------|
//! | 0 | `000` | `1` (scalar) |
//! | 1 | `001` | `e₁` |
//! | 2 | `010` | `e₂` |
//! | 3 | `011` | `e₁₂` |
//! | 4 | `100` | `e₃` |
//! | 5 | `101` | `e₁₃` |
//! | 6 | `110` | `e₂₃` |
//! | 7 | `111` | `e₁₂₃` |
//!
//! # Grade
//!
//! The **grade** of a blade is the number of basis vectors it contains,
//! which equals the number of set bits (popcount) in its index.
/// Returns the grade (number of basis vectors) of a blade given its index.
///
/// The grade equals the population count (number of 1-bits) in the binary
/// representation of the index.
///
/// # Arguments
///
/// * `index` - The blade index (bitmask of constituent basis vectors)
///
/// # Returns
///
/// The grade of the blade, from 0 (scalar) to N (pseudoscalar in N dimensions).
///
/// # Examples
///
/// ```
/// use clifford::basis::grade_of_blade;
///
/// assert_eq!(grade_of_blade(0b000), 0); // scalar
/// assert_eq!(grade_of_blade(0b001), 1); // e₁ (vector)
/// assert_eq!(grade_of_blade(0b011), 2); // e₁₂ (bivector)
/// assert_eq!(grade_of_blade(0b111), 3); // e₁₂₃ (trivector)
/// ```
pub const
/// Returns the number of blades of a given grade in a space of given dimension.
///
/// This computes the binomial coefficient `C(dim, grade)`, which counts
/// how many ways we can choose `grade` basis vectors from `dim` total.
///
/// # Arguments
///
/// * `dim` - The dimension of the vector space
/// * `grade` - The grade to count blades for
///
/// # Returns
///
/// The number of basis blades of the specified grade.
///
/// # Examples
///
/// ```
/// use clifford::basis::blades_of_grade;
///
/// // In 3D, there is 1 scalar, 3 vectors, 3 bivectors, 1 trivector
/// assert_eq!(blades_of_grade(3, 0), 1);
/// assert_eq!(blades_of_grade(3, 1), 3);
/// assert_eq!(blades_of_grade(3, 2), 3);
/// assert_eq!(blades_of_grade(3, 3), 1);
///
/// // In 4D, there are 6 bivectors (4 choose 2)
/// assert_eq!(blades_of_grade(4, 2), 6);
/// ```
pub const
/// Computes the binomial coefficient C(n, k) = n! / (k! * (n-k)!).
///
/// Uses an iterative algorithm that avoids overflow for reasonable inputs.
///
/// # Arguments
///
/// * `n` - The total number of items
/// * `k` - The number of items to choose
///
/// # Returns
///
/// The number of ways to choose `k` items from `n` items.
pub const
/// Returns the index of the first blade of a given grade.
///
/// Blades are ordered by grade, then by index within grade.
/// This returns the starting index for a particular grade in that ordering.
///
/// # Arguments
///
/// * `dim` - The dimension of the vector space
/// * `grade` - The grade to find the start index for
///
/// # Returns
///
/// The cumulative count of all blades with grade less than `grade`.
///
/// # Examples
///
/// ```
/// use clifford::basis::grade_start_index;
///
/// // In 3D: grades 0,1,2,3 have 1,3,3,1 blades
/// assert_eq!(grade_start_index(3, 0), 0); // scalars start at 0
/// assert_eq!(grade_start_index(3, 1), 1); // vectors start at 1
/// assert_eq!(grade_start_index(3, 2), 4); // bivectors start at 4
/// assert_eq!(grade_start_index(3, 3), 7); // trivectors start at 7
/// ```
pub const