|
| 1 | +use super::{CompoundField, CompoundType, H5Type, TypeDescriptor}; |
| 2 | + |
| 3 | +use std::mem::size_of; |
| 4 | + |
| 5 | +use num_complex::Complex; |
| 6 | + |
| 7 | +unsafe impl<T: H5Type> H5Type for Complex<T> { |
| 8 | + fn type_descriptor() -> TypeDescriptor { |
| 9 | + // Complex<T> should be FFI-equivalent to [T; 2] |
| 10 | + // https://docs.rs/num-complex/0.4.3/num_complex/struct.Complex.html#representation-and-foreign-function-interface-compatibility |
| 11 | + TypeDescriptor::Compound(CompoundType { |
| 12 | + fields: vec![ |
| 13 | + // Compatible with h5py definition of complex |
| 14 | + CompoundField::typed::<T>("r", 0, 0), |
| 15 | + CompoundField::typed::<T>("i", size_of::<T>(), 1), |
| 16 | + ], |
| 17 | + size: size_of::<T>() * 2, |
| 18 | + }) |
| 19 | + } |
| 20 | +} |
| 21 | + |
| 22 | +#[cfg(test)] |
| 23 | +mod tests { |
| 24 | + use super::*; |
| 25 | + use num_complex::{Complex32, Complex64}; |
| 26 | + use std::mem::size_of_val; |
| 27 | + |
| 28 | + #[test] |
| 29 | + fn complex() { |
| 30 | + assert_eq!(Complex32::type_descriptor().size(), 8); |
| 31 | + assert_eq!(Complex32::type_descriptor().size(), size_of::<Complex32>()); |
| 32 | + assert_eq!(Complex64::type_descriptor().size(), 16); |
| 33 | + assert_eq!(Complex64::type_descriptor().size(), size_of::<Complex64>()); |
| 34 | + } |
| 35 | + |
| 36 | + #[test] |
| 37 | + fn alignment() { |
| 38 | + use std::ptr::addr_of; |
| 39 | + |
| 40 | + let a = Complex { re: 0.0, im: 1.0 }; |
| 41 | + |
| 42 | + assert_eq!(size_of_val(&a), size_of_val(&a.re) + size_of_val(&a.im)); |
| 43 | + assert_eq!(size_of_val(&a.re), size_of_val(&a.im)); |
| 44 | + |
| 45 | + let base: *const u8 = addr_of!(a).cast::<u8>(); |
| 46 | + let ptr_r = addr_of!(a.re).cast::<u8>(); |
| 47 | + let ptr_i = addr_of!(a.im).cast::<u8>(); |
| 48 | + |
| 49 | + assert_eq!(unsafe { ptr_r.offset_from(base) }, 0); |
| 50 | + assert_eq!(unsafe { ptr_i.offset_from(base) }, size_of_val(&a.re) as isize); |
| 51 | + } |
| 52 | +} |
0 commit comments