autd3_driver/
autd3_device.rs

1use crate::{
2    common::mm,
3    geometry::{Device, Isometry, Point3, Transducer, Translation, UnitQuaternion},
4};
5use getset::Getters;
6use std::fmt::Debug;
7
8/// AUTD3 device.
9#[derive(Clone, Copy, Debug, Getters)]
10pub struct AUTD3<R: Into<UnitQuaternion> + Debug> {
11    /// The global position of the AUTD3 device.
12    pub pos: Point3,
13    /// The rotation of the AUTD3 device.
14    pub rot: R,
15}
16
17impl Default for AUTD3<UnitQuaternion> {
18    fn default() -> Self {
19        Self {
20            pos: Point3::origin(),
21            rot: UnitQuaternion::identity(),
22        }
23    }
24}
25
26impl AUTD3<UnitQuaternion> {
27    /// The number of transducers in x-axis.
28    pub const NUM_TRANS_X: usize = 18;
29    /// The number of transducers in y-axis.
30    pub const NUM_TRANS_Y: usize = 14;
31    /// The number of transducers in a unit.
32    pub const NUM_TRANS_IN_UNIT: usize = Self::NUM_TRANS_X * Self::NUM_TRANS_Y - 3;
33    /// The spacing between transducers.
34    pub const TRANS_SPACING: f32 = 10.16 * mm;
35    /// The width of the device (including the substrate).
36    pub const DEVICE_WIDTH: f32 = 192.0 * mm;
37    /// The height of the device (including the substrate).
38    pub const DEVICE_HEIGHT: f32 = 151.4 * mm;
39
40    #[must_use]
41    const fn is_missing_transducer(x: usize, y: usize) -> bool {
42        if Self::NUM_TRANS_X <= x || Self::NUM_TRANS_Y <= y {
43            return true;
44        }
45        y == 1 && (x == 1 || x == 2 || x == 16)
46    }
47
48    /// Gets the index in x- and y-axis from the transducer index.
49    #[must_use]
50    pub const fn grid_id(idx: usize) -> (usize, usize) {
51        let local_id = idx % Self::NUM_TRANS_IN_UNIT;
52        let uid = match local_id {
53            0..19 => local_id,
54            19..32 => local_id + 2,
55            _ => local_id + 3,
56        };
57        (uid % Self::NUM_TRANS_X, uid / Self::NUM_TRANS_X)
58    }
59}
60
61impl<R: Into<UnitQuaternion> + Debug> AUTD3<R> {
62    /// Create a new AUTD3 device.
63    #[must_use]
64    pub fn new(pos: Point3, rot: R) -> Self {
65        Self { pos, rot }
66    }
67}
68
69impl<R: Into<UnitQuaternion> + Debug> From<AUTD3<R>> for Device {
70    fn from(autd3: AUTD3<R>) -> Self {
71        let rot = autd3.rot.into();
72        let isometry = Isometry {
73            rotation: rot,
74            translation: Translation::from(autd3.pos),
75        };
76        Self::new(
77            rot,
78            itertools::iproduct!(0..AUTD3::NUM_TRANS_Y, 0..AUTD3::NUM_TRANS_X)
79                .filter(|&(y, x)| !AUTD3::is_missing_transducer(x, y))
80                .map(|(y, x)| {
81                    isometry
82                        * Point3::new(
83                            x as f32 * AUTD3::TRANS_SPACING,
84                            y as f32 * AUTD3::TRANS_SPACING,
85                            0.,
86                        )
87                })
88                .map(|p| Transducer::new(p.xyz()))
89                .collect(),
90        )
91    }
92}
93
94#[cfg(test)]
95pub(crate) mod tests {
96    use autd3_core::geometry::{Geometry, Vector3};
97
98    use super::*;
99
100    pub fn create_device() -> Device {
101        AUTD3::default().into()
102    }
103
104    pub fn create_geometry(n: usize) -> crate::geometry::Geometry {
105        Geometry::new((0..n).map(|_| create_device()).collect())
106    }
107
108    #[test]
109    fn num_devices() {
110        let dev: Device = AUTD3::default().into();
111        assert_eq!(AUTD3::NUM_TRANS_IN_UNIT, dev.num_transducers());
112    }
113
114    #[rstest::rstest]
115    #[test]
116    #[case(
117        Point3::new(0., 0., 0.),
118        0,
119        Point3::origin(),
120        UnitQuaternion::identity()
121    )]
122    #[case(
123        Point3::new(AUTD3::TRANS_SPACING, 0., 0.),
124        1,
125        Point3::origin(),
126        UnitQuaternion::identity()
127    )]
128    #[case(
129        Point3::new(0., AUTD3::TRANS_SPACING, 0.),
130        18,
131        Point3::origin(),
132        UnitQuaternion::identity()
133    )]
134    #[case(Point3::new(17. * AUTD3::TRANS_SPACING, 13. * AUTD3::TRANS_SPACING, 0.), 248, Point3::origin(), UnitQuaternion::identity())]
135    #[case(
136        Point3::new(1., 2., 3.),
137        0,
138        Point3::new(1., 2., 3.),
139        UnitQuaternion::identity()
140    )]
141    #[case(
142        Point3::new(AUTD3::TRANS_SPACING + 1., 2., 3.),
143        1,
144        Point3::new(1., 2., 3.),
145        UnitQuaternion::identity()
146    )]
147    #[case(
148        Point3::new(1., AUTD3::TRANS_SPACING + 2., 3.),
149        18,
150        Point3::new(1., 2., 3.),
151        UnitQuaternion::identity()
152    )]
153    #[case(Point3::new(17. * AUTD3::TRANS_SPACING + 1., 13. * AUTD3::TRANS_SPACING + 2., 3.), 248, Point3::new(1., 2., 3.), UnitQuaternion::identity())]
154    #[case(
155        Point3::new(0., 0., 0.),
156        0,
157        Point3::origin(),
158        UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2)
159    )]
160    #[case(
161        Point3::new(0., 0., -AUTD3::TRANS_SPACING),
162        1,
163        Point3::origin(),
164        UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2)
165    )]
166    #[case(
167        Point3::new(0., AUTD3::TRANS_SPACING, 0.),
168        18,
169        Point3::origin(),
170        UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2)
171    )]
172    #[case(Point3::new(0., 13. * AUTD3::TRANS_SPACING, -17. * AUTD3::TRANS_SPACING), 248, Point3::origin(), UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2))]
173    #[case(
174        Point3::new(1., 2., 3.),
175        0,
176        Point3::new(1., 2., 3.),
177        UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2)
178    )]
179    #[case(
180        Point3::new(1., 2., 3. - AUTD3::TRANS_SPACING),
181        1,
182        Point3::new(1., 2., 3.),
183        UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2)
184    )]
185    #[case(
186        Point3::new(1., 2. + AUTD3::TRANS_SPACING, 3.),
187        18,
188        Point3::new(1., 2., 3.),
189        UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2)
190    )]
191    #[case(Point3::new(1., 2. + 13. * AUTD3::TRANS_SPACING, 3. - 17. * AUTD3::TRANS_SPACING), 248, Point3::new(1., 2., 3.), UnitQuaternion::new(Vector3::y() * std::f32::consts::FRAC_PI_2))]
192    fn position(
193        #[case] expected: Point3,
194        #[case] idx: usize,
195        #[case] pos: Point3,
196        #[case] rot: impl Into<UnitQuaternion> + Debug,
197    ) {
198        let dev: Device = AUTD3 { pos, rot }.into();
199        approx::assert_relative_eq!(expected.x, dev[idx].position().x, epsilon = 1e-6);
200        approx::assert_relative_eq!(expected.y, dev[idx].position().y, epsilon = 1e-6);
201        approx::assert_relative_eq!(expected.z, dev[idx].position().z, epsilon = 1e-6);
202    }
203
204    #[rstest::rstest]
205    #[test]
206    #[case(0, 0, false)]
207    #[case(1, 0, false)]
208    #[case(2, 0, false)]
209    #[case(3, 0, false)]
210    #[case(4, 0, false)]
211    #[case(5, 0, false)]
212    #[case(6, 0, false)]
213    #[case(7, 0, false)]
214    #[case(8, 0, false)]
215    #[case(9, 0, false)]
216    #[case(10, 0, false)]
217    #[case(11, 0, false)]
218    #[case(12, 0, false)]
219    #[case(13, 0, false)]
220    #[case(14, 0, false)]
221    #[case(15, 0, false)]
222    #[case(16, 0, false)]
223    #[case(17, 0, false)]
224    #[case(0, 1, false)]
225    #[case(1, 1, true)]
226    #[case(2, 1, true)]
227    #[case(3, 1, false)]
228    #[case(4, 1, false)]
229    #[case(5, 1, false)]
230    #[case(6, 1, false)]
231    #[case(7, 1, false)]
232    #[case(8, 1, false)]
233    #[case(9, 1, false)]
234    #[case(10, 1, false)]
235    #[case(11, 1, false)]
236    #[case(12, 1, false)]
237    #[case(13, 1, false)]
238    #[case(14, 1, false)]
239    #[case(15, 1, false)]
240    #[case(16, 1, true)]
241    #[case(17, 1, false)]
242    #[case(0, 2, false)]
243    #[case(1, 2, false)]
244    #[case(2, 2, false)]
245    #[case(3, 2, false)]
246    #[case(4, 2, false)]
247    #[case(5, 2, false)]
248    #[case(6, 2, false)]
249    #[case(7, 2, false)]
250    #[case(8, 2, false)]
251    #[case(9, 2, false)]
252    #[case(10, 2, false)]
253    #[case(11, 2, false)]
254    #[case(12, 2, false)]
255    #[case(13, 2, false)]
256    #[case(14, 2, false)]
257    #[case(15, 2, false)]
258    #[case(16, 2, false)]
259    #[case(17, 2, false)]
260    #[case(0, 3, false)]
261    #[case(1, 3, false)]
262    #[case(2, 3, false)]
263    #[case(3, 3, false)]
264    #[case(4, 3, false)]
265    #[case(5, 3, false)]
266    #[case(6, 3, false)]
267    #[case(7, 3, false)]
268    #[case(8, 3, false)]
269    #[case(9, 3, false)]
270    #[case(10, 3, false)]
271    #[case(11, 3, false)]
272    #[case(12, 3, false)]
273    #[case(13, 3, false)]
274    #[case(14, 3, false)]
275    #[case(15, 3, false)]
276    #[case(16, 3, false)]
277    #[case(17, 3, false)]
278    #[case(0, 4, false)]
279    #[case(1, 4, false)]
280    #[case(2, 4, false)]
281    #[case(3, 4, false)]
282    #[case(4, 4, false)]
283    #[case(5, 4, false)]
284    #[case(6, 4, false)]
285    #[case(7, 4, false)]
286    #[case(8, 4, false)]
287    #[case(9, 4, false)]
288    #[case(10, 4, false)]
289    #[case(11, 4, false)]
290    #[case(12, 4, false)]
291    #[case(13, 4, false)]
292    #[case(14, 4, false)]
293    #[case(15, 4, false)]
294    #[case(16, 4, false)]
295    #[case(17, 4, false)]
296    #[case(0, 5, false)]
297    #[case(1, 5, false)]
298    #[case(2, 5, false)]
299    #[case(3, 5, false)]
300    #[case(4, 5, false)]
301    #[case(5, 5, false)]
302    #[case(6, 5, false)]
303    #[case(7, 5, false)]
304    #[case(8, 5, false)]
305    #[case(9, 5, false)]
306    #[case(10, 5, false)]
307    #[case(11, 5, false)]
308    #[case(12, 5, false)]
309    #[case(13, 5, false)]
310    #[case(14, 5, false)]
311    #[case(15, 5, false)]
312    #[case(16, 5, false)]
313    #[case(17, 5, false)]
314    #[case(0, 6, false)]
315    #[case(1, 6, false)]
316    #[case(2, 6, false)]
317    #[case(3, 6, false)]
318    #[case(4, 6, false)]
319    #[case(5, 6, false)]
320    #[case(6, 6, false)]
321    #[case(7, 6, false)]
322    #[case(8, 6, false)]
323    #[case(9, 6, false)]
324    #[case(10, 6, false)]
325    #[case(11, 6, false)]
326    #[case(12, 6, false)]
327    #[case(13, 6, false)]
328    #[case(14, 6, false)]
329    #[case(15, 6, false)]
330    #[case(16, 6, false)]
331    #[case(17, 6, false)]
332    #[case(0, 7, false)]
333    #[case(1, 7, false)]
334    #[case(2, 7, false)]
335    #[case(3, 7, false)]
336    #[case(4, 7, false)]
337    #[case(5, 7, false)]
338    #[case(6, 7, false)]
339    #[case(7, 7, false)]
340    #[case(8, 7, false)]
341    #[case(9, 7, false)]
342    #[case(10, 7, false)]
343    #[case(11, 7, false)]
344    #[case(12, 7, false)]
345    #[case(13, 7, false)]
346    #[case(14, 7, false)]
347    #[case(15, 7, false)]
348    #[case(16, 7, false)]
349    #[case(17, 7, false)]
350    #[case(0, 8, false)]
351    #[case(1, 8, false)]
352    #[case(2, 8, false)]
353    #[case(3, 8, false)]
354    #[case(4, 8, false)]
355    #[case(5, 8, false)]
356    #[case(6, 8, false)]
357    #[case(7, 8, false)]
358    #[case(8, 8, false)]
359    #[case(9, 8, false)]
360    #[case(10, 8, false)]
361    #[case(11, 8, false)]
362    #[case(12, 8, false)]
363    #[case(13, 8, false)]
364    #[case(14, 8, false)]
365    #[case(15, 8, false)]
366    #[case(16, 8, false)]
367    #[case(17, 8, false)]
368    #[case(0, 9, false)]
369    #[case(1, 9, false)]
370    #[case(2, 9, false)]
371    #[case(3, 9, false)]
372    #[case(4, 9, false)]
373    #[case(5, 9, false)]
374    #[case(6, 9, false)]
375    #[case(7, 9, false)]
376    #[case(8, 9, false)]
377    #[case(9, 9, false)]
378    #[case(10, 9, false)]
379    #[case(11, 9, false)]
380    #[case(12, 9, false)]
381    #[case(13, 9, false)]
382    #[case(14, 9, false)]
383    #[case(15, 9, false)]
384    #[case(16, 9, false)]
385    #[case(17, 9, false)]
386    #[case(0, 10, false)]
387    #[case(1, 10, false)]
388    #[case(2, 10, false)]
389    #[case(3, 10, false)]
390    #[case(4, 10, false)]
391    #[case(5, 10, false)]
392    #[case(6, 10, false)]
393    #[case(7, 10, false)]
394    #[case(8, 10, false)]
395    #[case(9, 10, false)]
396    #[case(10, 10, false)]
397    #[case(11, 10, false)]
398    #[case(12, 10, false)]
399    #[case(13, 10, false)]
400    #[case(14, 10, false)]
401    #[case(15, 10, false)]
402    #[case(16, 10, false)]
403    #[case(17, 10, false)]
404    #[case(0, 11, false)]
405    #[case(1, 11, false)]
406    #[case(2, 11, false)]
407    #[case(3, 11, false)]
408    #[case(4, 11, false)]
409    #[case(5, 11, false)]
410    #[case(6, 11, false)]
411    #[case(7, 11, false)]
412    #[case(8, 11, false)]
413    #[case(9, 11, false)]
414    #[case(10, 11, false)]
415    #[case(11, 11, false)]
416    #[case(12, 11, false)]
417    #[case(13, 11, false)]
418    #[case(14, 11, false)]
419    #[case(15, 11, false)]
420    #[case(16, 11, false)]
421    #[case(17, 11, false)]
422    #[case(0, 12, false)]
423    #[case(1, 12, false)]
424    #[case(2, 12, false)]
425    #[case(3, 12, false)]
426    #[case(4, 12, false)]
427    #[case(5, 12, false)]
428    #[case(6, 12, false)]
429    #[case(7, 12, false)]
430    #[case(8, 12, false)]
431    #[case(9, 12, false)]
432    #[case(10, 12, false)]
433    #[case(11, 12, false)]
434    #[case(12, 12, false)]
435    #[case(13, 12, false)]
436    #[case(14, 12, false)]
437    #[case(15, 12, false)]
438    #[case(16, 12, false)]
439    #[case(17, 12, false)]
440    #[case(0, 13, false)]
441    #[case(1, 13, false)]
442    #[case(2, 13, false)]
443    #[case(3, 13, false)]
444    #[case(4, 13, false)]
445    #[case(5, 13, false)]
446    #[case(6, 13, false)]
447    #[case(7, 13, false)]
448    #[case(8, 13, false)]
449    #[case(9, 13, false)]
450    #[case(10, 13, false)]
451    #[case(11, 13, false)]
452    #[case(12, 13, false)]
453    #[case(13, 13, false)]
454    #[case(14, 13, false)]
455    #[case(15, 13, false)]
456    #[case(16, 13, false)]
457    #[case(17, 13, false)]
458    fn test_is_missing_transducer(#[case] x: usize, #[case] y: usize, #[case] expected: bool) {
459        assert_eq!(expected, AUTD3::is_missing_transducer(x, y));
460    }
461
462    #[test]
463    fn test_is_missing_transducer_out_of_range() {
464        itertools::iproduct!(18..=256, 0..=256).for_each(|(x, y)| {
465            assert!(AUTD3::is_missing_transducer(x, y));
466        });
467        itertools::iproduct!(0..=256, 14..=256).for_each(|(x, y)| {
468            assert!(AUTD3::is_missing_transducer(x, y));
469        });
470    }
471
472    #[rstest::rstest]
473    #[test]
474    #[case(0, (0, 0))]
475    #[case(1, (1, 0))]
476    #[case(2, (2, 0))]
477    #[case(3, (3, 0))]
478    #[case(4, (4, 0))]
479    #[case(5, (5, 0))]
480    #[case(6, (6, 0))]
481    #[case(7, (7, 0))]
482    #[case(8, (8, 0))]
483    #[case(9, (9, 0))]
484    #[case(10, (10, 0))]
485    #[case(11, (11, 0))]
486    #[case(12, (12, 0))]
487    #[case(13, (13, 0))]
488    #[case(14, (14, 0))]
489    #[case(15, (15, 0))]
490    #[case(16, (16, 0))]
491    #[case(17, (17, 0))]
492    #[case(18, (0, 1))]
493    #[case(19, (3, 1))]
494    #[case(20, (4, 1))]
495    #[case(21, (5, 1))]
496    #[case(22, (6, 1))]
497    #[case(23, (7, 1))]
498    #[case(24, (8, 1))]
499    #[case(25, (9, 1))]
500    #[case(26, (10, 1))]
501    #[case(27, (11, 1))]
502    #[case(28, (12, 1))]
503    #[case(29, (13, 1))]
504    #[case(30, (14, 1))]
505    #[case(31, (15, 1))]
506    #[case(32, (17, 1))]
507    #[case(33, (0, 2))]
508    #[case(34, (1, 2))]
509    #[case(35, (2, 2))]
510    #[case(36, (3, 2))]
511    #[case(37, (4, 2))]
512    #[case(38, (5, 2))]
513    #[case(39, (6, 2))]
514    #[case(40, (7, 2))]
515    #[case(41, (8, 2))]
516    #[case(42, (9, 2))]
517    #[case(43, (10, 2))]
518    #[case(44, (11, 2))]
519    #[case(45, (12, 2))]
520    #[case(46, (13, 2))]
521    #[case(47, (14, 2))]
522    #[case(48, (15, 2))]
523    #[case(49, (16, 2))]
524    #[case(50, (17, 2))]
525    #[case(51, (0, 3))]
526    #[case(52, (1, 3))]
527    #[case(53, (2, 3))]
528    #[case(54, (3, 3))]
529    #[case(55, (4, 3))]
530    #[case(56, (5, 3))]
531    #[case(57, (6, 3))]
532    #[case(58, (7, 3))]
533    #[case(59, (8, 3))]
534    #[case(60, (9, 3))]
535    #[case(61, (10, 3))]
536    #[case(62, (11, 3))]
537    #[case(63, (12, 3))]
538    #[case(64, (13, 3))]
539    #[case(65, (14, 3))]
540    #[case(66, (15, 3))]
541    #[case(67, (16, 3))]
542    #[case(68, (17, 3))]
543    #[case(69, (0, 4))]
544    #[case(70, (1, 4))]
545    #[case(71, (2, 4))]
546    #[case(72, (3, 4))]
547    #[case(73, (4, 4))]
548    #[case(74, (5, 4))]
549    #[case(75, (6, 4))]
550    #[case(76, (7, 4))]
551    #[case(77, (8, 4))]
552    #[case(78, (9, 4))]
553    #[case(79, (10, 4))]
554    #[case(80, (11, 4))]
555    #[case(81, (12, 4))]
556    #[case(82, (13, 4))]
557    #[case(83, (14, 4))]
558    #[case(84, (15, 4))]
559    #[case(85, (16, 4))]
560    #[case(86, (17, 4))]
561    #[case(87, (0, 5))]
562    #[case(88, (1, 5))]
563    #[case(89, (2, 5))]
564    #[case(90, (3, 5))]
565    #[case(91, (4, 5))]
566    #[case(92, (5, 5))]
567    #[case(93, (6, 5))]
568    #[case(94, (7, 5))]
569    #[case(95, (8, 5))]
570    #[case(96, (9, 5))]
571    #[case(97, (10, 5))]
572    #[case(98, (11, 5))]
573    #[case(99, (12, 5))]
574    #[case(100, (13, 5))]
575    #[case(101, (14, 5))]
576    #[case(102, (15, 5))]
577    #[case(103, (16, 5))]
578    #[case(104, (17, 5))]
579    #[case(105, (0, 6))]
580    #[case(106, (1, 6))]
581    #[case(107, (2, 6))]
582    #[case(108, (3, 6))]
583    #[case(109, (4, 6))]
584    #[case(110, (5, 6))]
585    #[case(111, (6, 6))]
586    #[case(112, (7, 6))]
587    #[case(113, (8, 6))]
588    #[case(114, (9, 6))]
589    #[case(115, (10, 6))]
590    #[case(116, (11, 6))]
591    #[case(117, (12, 6))]
592    #[case(118, (13, 6))]
593    #[case(119, (14, 6))]
594    #[case(120, (15, 6))]
595    #[case(121, (16, 6))]
596    #[case(122, (17, 6))]
597    #[case(123, (0, 7))]
598    #[case(124, (1, 7))]
599    #[case(125, (2, 7))]
600    #[case(126, (3, 7))]
601    #[case(127, (4, 7))]
602    #[case(128, (5, 7))]
603    #[case(129, (6, 7))]
604    #[case(130, (7, 7))]
605    #[case(131, (8, 7))]
606    #[case(132, (9, 7))]
607    #[case(133, (10, 7))]
608    #[case(134, (11, 7))]
609    #[case(135, (12, 7))]
610    #[case(136, (13, 7))]
611    #[case(137, (14, 7))]
612    #[case(138, (15, 7))]
613    #[case(139, (16, 7))]
614    #[case(140, (17, 7))]
615    #[case(141, (0, 8))]
616    #[case(142, (1, 8))]
617    #[case(143, (2, 8))]
618    #[case(144, (3, 8))]
619    #[case(145, (4, 8))]
620    #[case(146, (5, 8))]
621    #[case(147, (6, 8))]
622    #[case(148, (7, 8))]
623    #[case(149, (8, 8))]
624    #[case(150, (9, 8))]
625    #[case(151, (10, 8))]
626    #[case(152, (11, 8))]
627    #[case(153, (12, 8))]
628    #[case(154, (13, 8))]
629    #[case(155, (14, 8))]
630    #[case(156, (15, 8))]
631    #[case(157, (16, 8))]
632    #[case(158, (17, 8))]
633    #[case(159, (0, 9))]
634    #[case(160, (1, 9))]
635    #[case(161, (2, 9))]
636    #[case(162, (3, 9))]
637    #[case(163, (4, 9))]
638    #[case(164, (5, 9))]
639    #[case(165, (6, 9))]
640    #[case(166, (7, 9))]
641    #[case(167, (8, 9))]
642    #[case(168, (9, 9))]
643    #[case(169, (10, 9))]
644    #[case(170, (11, 9))]
645    #[case(171, (12, 9))]
646    #[case(172, (13, 9))]
647    #[case(173, (14, 9))]
648    #[case(174, (15, 9))]
649    #[case(175, (16, 9))]
650    #[case(176, (17, 9))]
651    #[case(177, (0, 10))]
652    #[case(178, (1, 10))]
653    #[case(179, (2, 10))]
654    #[case(180, (3, 10))]
655    #[case(181, (4, 10))]
656    #[case(182, (5, 10))]
657    #[case(183, (6, 10))]
658    #[case(184, (7, 10))]
659    #[case(185, (8, 10))]
660    #[case(186, (9, 10))]
661    #[case(187, (10, 10))]
662    #[case(188, (11, 10))]
663    #[case(189, (12, 10))]
664    #[case(190, (13, 10))]
665    #[case(191, (14, 10))]
666    #[case(192, (15, 10))]
667    #[case(193, (16, 10))]
668    #[case(194, (17, 10))]
669    #[case(195, (0, 11))]
670    #[case(196, (1, 11))]
671    #[case(197, (2, 11))]
672    #[case(198, (3, 11))]
673    #[case(199, (4, 11))]
674    #[case(200, (5, 11))]
675    #[case(201, (6, 11))]
676    #[case(202, (7, 11))]
677    #[case(203, (8, 11))]
678    #[case(204, (9, 11))]
679    #[case(205, (10, 11))]
680    #[case(206, (11, 11))]
681    #[case(207, (12, 11))]
682    #[case(208, (13, 11))]
683    #[case(209, (14, 11))]
684    #[case(210, (15, 11))]
685    #[case(211, (16, 11))]
686    #[case(212, (17, 11))]
687    #[case(213, (0, 12))]
688    #[case(214, (1, 12))]
689    #[case(215, (2, 12))]
690    #[case(216, (3, 12))]
691    #[case(217, (4, 12))]
692    #[case(218, (5, 12))]
693    #[case(219, (6, 12))]
694    #[case(220, (7, 12))]
695    #[case(221, (8, 12))]
696    #[case(222, (9, 12))]
697    #[case(223, (10, 12))]
698    #[case(224, (11, 12))]
699    #[case(225, (12, 12))]
700    #[case(226, (13, 12))]
701    #[case(227, (14, 12))]
702    #[case(228, (15, 12))]
703    #[case(229, (16, 12))]
704    #[case(230, (17, 12))]
705    #[case(231, (0, 13))]
706    #[case(232, (1, 13))]
707    #[case(233, (2, 13))]
708    #[case(234, (3, 13))]
709    #[case(235, (4, 13))]
710    #[case(236, (5, 13))]
711    #[case(237, (6, 13))]
712    #[case(238, (7, 13))]
713    #[case(239, (8, 13))]
714    #[case(240, (9, 13))]
715    #[case(241, (10, 13))]
716    #[case(242, (11, 13))]
717    #[case(243, (12, 13))]
718    #[case(244, (13, 13))]
719    #[case(245, (14, 13))]
720    #[case(246, (15, 13))]
721    #[case(247, (16, 13))]
722    #[case(248, (17, 13))]
723    fn test_grid_id(#[case] idx: usize, #[case] expected: (usize, usize)) {
724        assert_eq!(expected, AUTD3::grid_id(idx));
725    }
726}