#![allow(clippy::module_name_repetitions, clippy::missing_panics_doc)]
use num_complex::Complex;
use std::borrow::Borrow;
use std::marker::PhantomData;
use std::os::raw::c_void;
use std::{mem, slice};
use conv::ConvUtil;
use super::{Address, Count};
use crate::ffi;
use crate::ffi::MPI_Datatype;
use crate::raw::traits::{AsRaw, FromRaw, MatchesRaw};
use crate::with_uninitialized;
pub mod traits {
pub use super::{
AsDatatype, Buffer, BufferMut, Collection, Datatype, Equivalence, Partitioned,
PartitionedBuffer, PartitionedBufferMut, Pointer, PointerMut, UncommittedDatatype,
};
}
#[derive(Copy, Clone, Debug)]
pub struct DatatypeRef<'a> {
datatype: MPI_Datatype,
phantom: PhantomData<&'a ()>,
}
unsafe impl<'a> AsRaw for DatatypeRef<'a> {
type Raw = MPI_Datatype;
fn as_raw(&self) -> Self::Raw {
self.datatype
}
}
impl<'a> FromRaw for DatatypeRef<'a> {
unsafe fn from_raw(datatype: MPI_Datatype) -> Self {
Self {
datatype,
phantom: PhantomData,
}
}
}
unsafe impl<'a> MatchesRaw for DatatypeRef<'a> {}
impl<'a> Datatype for DatatypeRef<'a> {}
impl<'a> UncommittedDatatype for DatatypeRef<'a> {
type DuplicatedDatatype = UserDatatype;
}
impl<'a> From<DatatypeRef<'a>> for UncommittedDatatypeRef<'a> {
fn from(datatype_ref: DatatypeRef<'a>) -> Self {
unsafe { UncommittedDatatypeRef::from_raw(datatype_ref.as_raw()) }
}
}
#[derive(Copy, Clone, Debug)]
pub struct UncommittedDatatypeRef<'a> {
datatype: MPI_Datatype,
phantom: PhantomData<&'a ()>,
}
unsafe impl<'a> AsRaw for UncommittedDatatypeRef<'a> {
type Raw = MPI_Datatype;
fn as_raw(&self) -> Self::Raw {
self.datatype
}
}
impl<'a> FromRaw for UncommittedDatatypeRef<'a> {
unsafe fn from_raw(datatype: MPI_Datatype) -> Self {
Self {
datatype,
phantom: PhantomData,
}
}
}
unsafe impl<'a> MatchesRaw for UncommittedDatatypeRef<'a> {}
impl<'a> UncommittedDatatype for UncommittedDatatypeRef<'a> {
type DuplicatedDatatype = UncommittedUserDatatype;
}
pub type SystemDatatype = DatatypeRef<'static>;
pub unsafe trait Equivalence {
type Out: Datatype;
fn equivalent_datatype() -> Self::Out;
}
macro_rules! equivalent_system_datatype {
($rstype:path, $mpitype:path) => {
unsafe impl Equivalence for $rstype {
type Out = SystemDatatype;
fn equivalent_datatype() -> Self::Out {
unsafe { DatatypeRef::from_raw($mpitype) }
}
}
};
}
equivalent_system_datatype!(bool, ffi::RSMPI_C_BOOL);
equivalent_system_datatype!(f32, ffi::RSMPI_FLOAT);
equivalent_system_datatype!(f64, ffi::RSMPI_DOUBLE);
equivalent_system_datatype!(Complex<f32>, ffi::RSMPI_COMPLEX);
equivalent_system_datatype!(Complex<f64>, ffi::RSMPI_DOUBLE_COMPLEX);
equivalent_system_datatype!(i8, ffi::RSMPI_INT8_T);
equivalent_system_datatype!(i16, ffi::RSMPI_INT16_T);
equivalent_system_datatype!(i32, ffi::RSMPI_INT32_T);
equivalent_system_datatype!(i64, ffi::RSMPI_INT64_T);
equivalent_system_datatype!(u8, ffi::RSMPI_UINT8_T);
equivalent_system_datatype!(u16, ffi::RSMPI_UINT16_T);
equivalent_system_datatype!(u32, ffi::RSMPI_UINT32_T);
equivalent_system_datatype!(u64, ffi::RSMPI_UINT64_T);
#[cfg(target_pointer_width = "32")]
equivalent_system_datatype!(usize, ffi::RSMPI_UINT32_T);
#[cfg(target_pointer_width = "32")]
equivalent_system_datatype!(isize, ffi::RSMPI_INT32_T);
#[cfg(target_pointer_width = "64")]
equivalent_system_datatype!(usize, ffi::RSMPI_UINT64_T);
#[cfg(target_pointer_width = "64")]
equivalent_system_datatype!(isize, ffi::RSMPI_INT64_T);
pub struct UserDatatype(MPI_Datatype);
impl UserDatatype {
pub fn contiguous<D>(count: Count, oldtype: &D) -> UserDatatype
where
D: UncommittedDatatype,
{
UncommittedUserDatatype::contiguous(count, oldtype).commit()
}
pub fn vector<D>(count: Count, blocklength: Count, stride: Count, oldtype: &D) -> UserDatatype
where
D: UncommittedDatatype,
{
UncommittedUserDatatype::vector(count, blocklength, stride, oldtype).commit()
}
pub fn heterogeneous_vector<D>(
count: Count,
blocklength: Count,
stride: Address,
oldtype: &D,
) -> UserDatatype
where
D: UncommittedDatatype,
{
UncommittedUserDatatype::heterogeneous_vector(count, blocklength, stride, oldtype).commit()
}
pub fn indexed<D>(blocklengths: &[Count], displacements: &[Count], oldtype: &D) -> UserDatatype
where
D: UncommittedDatatype,
{
UncommittedUserDatatype::indexed(blocklengths, displacements, oldtype).commit()
}
pub fn heterogeneous_indexed<D>(
blocklengths: &[Count],
displacements: &[Address],
oldtype: &D,
) -> UserDatatype
where
D: UncommittedDatatype,
{
UncommittedUserDatatype::heterogeneous_indexed(blocklengths, displacements, oldtype)
.commit()
}
pub fn indexed_block<D>(
blocklength: Count,
displacements: &[Count],
oldtype: &D,
) -> UserDatatype
where
D: UncommittedDatatype,
{
UncommittedUserDatatype::indexed_block(blocklength, displacements, oldtype).commit()
}
pub fn heterogeneous_indexed_block<D>(
blocklength: Count,
displacements: &[Address],
oldtype: &D,
) -> UserDatatype
where
D: UncommittedDatatype,
{
UncommittedUserDatatype::heterogeneous_indexed_block(blocklength, displacements, oldtype)
.commit()
}
pub fn structured<D>(
blocklengths: &[Count],
displacements: &[Address],
types: &[D],
) -> UserDatatype
where
D: UncommittedDatatype + MatchesRaw<Raw = MPI_Datatype>,
{
UncommittedUserDatatype::structured(blocklengths, displacements, types).commit()
}
pub fn as_ref(&self) -> DatatypeRef<'_> {
unsafe { DatatypeRef::from_raw(self.as_raw()) }
}
}
unsafe impl Send for UserDatatype {}
unsafe impl Sync for UserDatatype {}
impl Clone for UserDatatype {
fn clone(&self) -> Self {
self.dup()
}
}
impl Drop for UserDatatype {
fn drop(&mut self) {
unsafe {
ffi::MPI_Type_free(&mut self.0);
}
assert_eq!(self.0, unsafe { ffi::RSMPI_DATATYPE_NULL });
}
}
unsafe impl AsRaw for UserDatatype {
type Raw = MPI_Datatype;
fn as_raw(&self) -> Self::Raw {
self.0
}
}
impl FromRaw for UserDatatype {
unsafe fn from_raw(handle: MPI_Datatype) -> Self {
assert_ne!(handle, ffi::RSMPI_DATATYPE_NULL);
UserDatatype(handle)
}
}
unsafe impl MatchesRaw for UserDatatype {}
impl Datatype for UserDatatype {}
impl UncommittedDatatype for UserDatatype {
type DuplicatedDatatype = UserDatatype;
}
impl<'a> From<&'a UserDatatype> for DatatypeRef<'a> {
fn from(datatype: &'a UserDatatype) -> Self {
unsafe { DatatypeRef::from_raw(datatype.as_raw()) }
}
}
impl<'a> From<&'a UserDatatype> for UncommittedDatatypeRef<'a> {
fn from(datatype: &'a UserDatatype) -> Self {
unsafe { UncommittedDatatypeRef::from_raw(datatype.as_raw()) }
}
}
pub struct UncommittedUserDatatype(MPI_Datatype);
impl UncommittedUserDatatype {
pub fn contiguous<D>(count: Count, oldtype: &D) -> Self
where
D: UncommittedDatatype,
{
unsafe {
UncommittedUserDatatype(
with_uninitialized(|newtype| {
ffi::MPI_Type_contiguous(count, oldtype.as_raw(), newtype)
})
.1,
)
}
}
pub fn vector<D>(count: Count, blocklength: Count, stride: Count, oldtype: &D) -> Self
where
D: UncommittedDatatype,
{
unsafe {
UncommittedUserDatatype(
with_uninitialized(|newtype| {
ffi::MPI_Type_vector(count, blocklength, stride, oldtype.as_raw(), newtype)
})
.1,
)
}
}
pub fn heterogeneous_vector<D>(
count: Count,
blocklength: Count,
stride: Address,
oldtype: &D,
) -> Self
where
D: UncommittedDatatype,
{
unsafe {
UncommittedUserDatatype(
with_uninitialized(|newtype| {
ffi::MPI_Type_create_hvector(
count,
blocklength,
stride,
oldtype.as_raw(),
newtype,
)
})
.1,
)
}
}
pub fn indexed<D>(blocklengths: &[Count], displacements: &[Count], oldtype: &D) -> Self
where
D: UncommittedDatatype,
{
assert_eq!(
blocklengths.len(),
displacements.len(),
"'blocklengths' and 'displacements' must be the same length"
);
unsafe {
UncommittedUserDatatype(
with_uninitialized(|newtype| {
ffi::MPI_Type_indexed(
blocklengths.count(),
blocklengths.as_ptr(),
displacements.as_ptr(),
oldtype.as_raw(),
newtype,
)
})
.1,
)
}
}
pub fn heterogeneous_indexed<D>(
blocklengths: &[Count],
displacements: &[Address],
oldtype: &D,
) -> Self
where
D: UncommittedDatatype,
{
assert_eq!(
blocklengths.len(),
displacements.len(),
"'blocklengths' and 'displacements' must be the same length"
);
unsafe {
UncommittedUserDatatype(
with_uninitialized(|newtype| {
ffi::MPI_Type_create_hindexed(
blocklengths.count(),
blocklengths.as_ptr(),
displacements.as_ptr(),
oldtype.as_raw(),
newtype,
)
})
.1,
)
}
}
pub fn indexed_block<D>(blocklength: Count, displacements: &[Count], oldtype: &D) -> Self
where
D: UncommittedDatatype,
{
unsafe {
UncommittedUserDatatype(
with_uninitialized(|newtype| {
ffi::MPI_Type_create_indexed_block(
displacements.count(),
blocklength,
displacements.as_ptr(),
oldtype.as_raw(),
newtype,
)
})
.1,
)
}
}
pub fn heterogeneous_indexed_block<D>(
blocklength: Count,
displacements: &[Address],
oldtype: &D,
) -> Self
where
D: UncommittedDatatype,
{
unsafe {
UncommittedUserDatatype(
with_uninitialized(|newtype| {
ffi::MPI_Type_create_hindexed_block(
displacements.count(),
blocklength,
displacements.as_ptr(),
oldtype.as_raw(),
newtype,
)
})
.1,
)
}
}
pub fn structured<D>(blocklengths: &[Count], displacements: &[Address], types: &[D]) -> Self
where
D: UncommittedDatatype + MatchesRaw<Raw = MPI_Datatype>,
{
assert_eq!(
blocklengths.len(),
displacements.len(),
"'displacements', 'blocklengths', and 'types' must be the same length"
);
assert_eq!(
blocklengths.len(),
types.len(),
"'displacements', 'blocklengths', and 'types' must be the same length"
);
unsafe {
UncommittedUserDatatype(
with_uninitialized(|newtype| {
ffi::MPI_Type_create_struct(
blocklengths.count(),
blocklengths.as_ptr(),
displacements.as_ptr(),
types.as_ptr().cast(),
newtype,
)
})
.1,
)
}
}
pub fn commit(mut self) -> UserDatatype {
let handle = self.0;
unsafe {
ffi::MPI_Type_commit(&mut self.0);
}
mem::forget(self);
UserDatatype(handle)
}
pub fn as_ref(&self) -> UncommittedDatatypeRef<'_> {
unsafe { UncommittedDatatypeRef::from_raw(self.as_raw()) }
}
}
impl Clone for UncommittedUserDatatype {
fn clone(&self) -> Self {
self.dup()
}
}
impl Drop for UncommittedUserDatatype {
fn drop(&mut self) {
unsafe {
ffi::MPI_Type_free(&mut self.0);
}
assert_eq!(self.0, unsafe { ffi::RSMPI_DATATYPE_NULL });
}
}
unsafe impl AsRaw for UncommittedUserDatatype {
type Raw = MPI_Datatype;
fn as_raw(&self) -> Self::Raw {
self.0
}
}
impl FromRaw for UncommittedUserDatatype {
unsafe fn from_raw(handle: MPI_Datatype) -> Self {
assert_ne!(handle, ffi::RSMPI_DATATYPE_NULL);
UncommittedUserDatatype(handle)
}
}
unsafe impl MatchesRaw for UncommittedUserDatatype {}
impl UncommittedDatatype for UncommittedUserDatatype {
type DuplicatedDatatype = UncommittedUserDatatype;
}
impl<'a> From<&'a UncommittedUserDatatype> for UncommittedDatatypeRef<'a> {
fn from(datatype: &'a UncommittedUserDatatype) -> Self {
unsafe { UncommittedDatatypeRef::from_raw(datatype.as_raw()) }
}
}
pub trait Datatype: UncommittedDatatype {}
impl<'a, D> Datatype for &'a D where D: 'a + Datatype {}
pub trait UncommittedDatatype: AsRaw<Raw = MPI_Datatype> {
type DuplicatedDatatype: FromRaw<Raw = MPI_Datatype>;
fn dup(&self) -> Self::DuplicatedDatatype {
unsafe {
Self::DuplicatedDatatype::from_raw(
with_uninitialized(|newtype| ffi::MPI_Type_dup(self.as_raw(), newtype)).1,
)
}
}
}
impl<'a, D> UncommittedDatatype for &'a D
where
D: 'a + UncommittedDatatype,
{
type DuplicatedDatatype = <D as UncommittedDatatype>::DuplicatedDatatype;
}
pub unsafe trait AsDatatype {
type Out: Datatype;
fn as_datatype(&self) -> Self::Out;
}
unsafe impl<T> AsDatatype for T
where
T: Equivalence,
{
type Out = <T as Equivalence>::Out;
fn as_datatype(&self) -> Self::Out {
<T as Equivalence>::equivalent_datatype()
}
}
unsafe impl<T> AsDatatype for [T]
where
T: Equivalence,
{
type Out = <T as Equivalence>::Out;
fn as_datatype(&self) -> Self::Out {
<T as Equivalence>::equivalent_datatype()
}
}
#[doc(hidden)]
pub mod internal {
#[cfg(feature = "derive")]
pub fn check_derive_equivalence_universe_state(type_name: &str) {
use crate::environment::UNIVERSE_STATE;
let universe_state = UNIVERSE_STATE.read().unwrap();
if !crate::environment::is_initialized() {
panic!(
"\n\
RSMPI PANIC: Pre-MPI_Init datatype initialization\n\
\n\
Application attempted to initialize datatype of #[derive(Equivalence)] for \
`{}` before initializing rsmpi. You must first initialize rsmpi before attempting \
to use a custom type in an MPI call.\n",
type_name
);
}
let universe_state = universe_state.as_ref().unwrap();
if crate::environment::is_finalized() {
panic!(
"\n\
RSMPI PANIC: Post-MPI_Finalize datatype initialization.\n\
\n\
Application attempted to initialize datatype of #[derive(Equivalence)] for \
`{0}` after finalizing rsmpi. You must not attempt to use `{0}` in an MPI context \
after finalizing rsmpi.\n",
type_name
);
}
if crate::environment::threading_support() != crate::Threading::Multiple {
if universe_state.main_thread != std::thread::current().id() {
panic!(
"\n\
RSMPI PANIC: Invalid threaded datatype initialization\n\
\n\
Application attempted to initialize the datatype of #[derive(Equivalence)]
for `{0}` from a different thread than that which initialized `rsmpi`. This \
is only supported when rsmpi is initialized with \
`mpi::Threading::Multiple`. Please explicitly call \
`{0}::equivalent_datatype()` at least once from the same thread as you call \
`rsmpi::initialize*`, or initialize MPI using \
`mpi::initialize_with_threading(mpi::Threading::Multiple)`.\n",
type_name
)
}
}
}
}
pub unsafe trait Collection {
fn count(&self) -> Count;
}
unsafe impl<T> Collection for T
where
T: Equivalence,
{
fn count(&self) -> Count {
1
}
}
unsafe impl<T> Collection for [T]
where
T: Equivalence,
{
fn count(&self) -> Count {
self.len()
.value_as()
.expect("Length of slice cannot be expressed as an MPI Count.")
}
}
pub unsafe trait Pointer {
fn pointer(&self) -> *const c_void;
}
unsafe impl<T> Pointer for T
where
T: Equivalence,
{
fn pointer(&self) -> *const c_void {
let p: *const T = self;
p.cast::<c_void>()
}
}
unsafe impl<T> Pointer for [T]
where
T: Equivalence,
{
fn pointer(&self) -> *const c_void {
self.as_ptr().cast()
}
}
pub unsafe trait PointerMut {
fn pointer_mut(&mut self) -> *mut c_void;
}
unsafe impl<T> PointerMut for T
where
T: Equivalence,
{
fn pointer_mut(&mut self) -> *mut c_void {
let p: *mut T = self;
p.cast::<c_void>()
}
}
unsafe impl<T> PointerMut for [T]
where
T: Equivalence,
{
fn pointer_mut(&mut self) -> *mut c_void {
self.as_mut_ptr().cast()
}
}
pub unsafe trait Buffer: Pointer + Collection + AsDatatype {}
unsafe impl<T> Buffer for T where T: Equivalence {}
unsafe impl<T> Buffer for [T] where T: Equivalence {}
pub unsafe trait BufferMut: PointerMut + Collection + AsDatatype {}
unsafe impl<T> BufferMut for T where T: Equivalence {}
unsafe impl<T> BufferMut for [T] where T: Equivalence {}
#[derive(Copy, Clone, Debug)]
pub struct DynBuffer<'a> {
ptr: *const c_void,
len: Count,
datatype: DatatypeRef<'a>,
}
unsafe impl<'a> Send for DynBuffer<'a> {}
unsafe impl<'a> Sync for DynBuffer<'a> {}
unsafe impl<'a> Collection for DynBuffer<'a> {
fn count(&self) -> Count {
self.len
}
}
unsafe impl<'a> Pointer for DynBuffer<'a> {
fn pointer(&self) -> *const c_void {
self.ptr
}
}
unsafe impl<'a> AsDatatype for DynBuffer<'a> {
type Out = DatatypeRef<'a>;
fn as_datatype(&self) -> Self::Out {
self.datatype
}
}
unsafe impl<'a> Buffer for DynBuffer<'a> {}
impl<'a> DynBuffer<'a> {
pub fn new<T: Equivalence>(buf: &'a [T]) -> Self {
unsafe {
let datatype = DatatypeRef::from_raw(T::equivalent_datatype().as_raw());
Self::from_raw(buf.as_ptr(), buf.count(), datatype)
}
}
pub fn is<T: Equivalence>(&self) -> bool {
self.as_datatype().as_raw() == T::equivalent_datatype().as_raw()
}
pub fn downcast<T: Equivalence>(self) -> Option<&'a [T]> {
if self.is::<T>() {
unsafe { Some(slice::from_raw_parts(self.as_ptr().cast(), self.len())) }
} else {
None
}
}
pub unsafe fn from_raw<T>(ptr: *const T, len: Count, datatype: DatatypeRef<'a>) -> Self {
debug_assert!(!ptr.is_null());
Self {
ptr: ptr.cast(),
len,
datatype,
}
}
pub fn len(&self) -> usize {
self.count()
.value_as()
.expect("Length of DynBuffer cannot be expressed as a usize")
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn as_ptr(&self) -> *const c_void {
self.ptr
}
}
#[derive(Debug)]
pub struct DynBufferMut<'a> {
ptr: *mut c_void,
len: Count,
datatype: DatatypeRef<'a>,
}
unsafe impl<'a> Send for DynBufferMut<'a> {}
unsafe impl<'a> Sync for DynBufferMut<'a> {}
unsafe impl<'a> Collection for DynBufferMut<'a> {
fn count(&self) -> Count {
self.len
}
}
unsafe impl<'a> Pointer for DynBufferMut<'a> {
fn pointer(&self) -> *const c_void {
self.ptr
}
}
unsafe impl<'a> PointerMut for DynBufferMut<'a> {
fn pointer_mut(&mut self) -> *mut c_void {
self.ptr
}
}
unsafe impl<'a> Buffer for DynBufferMut<'a> {}
unsafe impl<'a> BufferMut for DynBufferMut<'a> {}
unsafe impl<'a> AsDatatype for DynBufferMut<'a> {
type Out = DatatypeRef<'a>;
fn as_datatype(&self) -> Self::Out {
self.datatype
}
}
impl<'a> DynBufferMut<'a> {
pub fn new<T: Equivalence>(buf: &'a mut [T]) -> Self {
unsafe {
let datatype = DatatypeRef::from_raw(T::equivalent_datatype().as_raw());
Self::from_raw(buf.as_mut_ptr(), buf.count(), datatype)
}
}
pub fn is<T: Equivalence>(&self) -> bool {
self.as_datatype().as_raw() == T::equivalent_datatype().as_raw()
}
pub fn downcast<T: Equivalence>(mut self) -> Option<&'a mut [T]> {
if self.is::<T>() {
unsafe {
Some(slice::from_raw_parts_mut(
self.as_mut_ptr().cast(),
self.len(),
))
}
} else {
None
}
}
pub unsafe fn from_raw<T>(ptr: *mut T, len: Count, datatype: DatatypeRef<'a>) -> Self {
debug_assert!(!ptr.is_null());
Self {
ptr: ptr.cast(),
len,
datatype,
}
}
pub fn len(&self) -> usize {
self.count()
.value_as()
.expect("Length of DynBufferMut cannot be expressed as a usize")
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn as_ptr(&self) -> *const c_void {
self.ptr
}
pub fn as_mut_ptr(&mut self) -> *mut c_void {
self.ptr
}
pub fn reborrow(&self) -> DynBuffer {
unsafe { DynBuffer::from_raw(self.as_ptr(), self.count(), self.as_datatype()) }
}
pub fn reborrow_mut(&mut self) -> DynBufferMut {
unsafe { DynBufferMut::from_raw(self.as_mut_ptr(), self.count(), self.as_datatype()) }
}
pub fn downgrade(self) -> DynBuffer<'a> {
unsafe { DynBuffer::from_raw(self.as_ptr(), self.count(), self.as_datatype()) }
}
}
pub struct View<'d, 'b, D, B: ?Sized>
where
D: 'd + Datatype,
B: 'b + Pointer,
{
datatype: &'d D,
count: Count,
buffer: &'b B,
}
impl<'d, 'b, D, B: ?Sized> View<'d, 'b, D, B>
where
D: 'd + Datatype,
B: 'b + Pointer,
{
pub unsafe fn with_count_and_datatype(
buffer: &'b B,
count: Count,
datatype: &'d D,
) -> View<'d, 'b, D, B> {
View {
datatype,
count,
buffer,
}
}
}
unsafe impl<'d, 'b, D, B: ?Sized> AsDatatype for View<'d, 'b, D, B>
where
D: 'd + Datatype,
B: 'b + Pointer,
{
type Out = &'d D;
fn as_datatype(&self) -> Self::Out {
self.datatype
}
}
unsafe impl<'d, 'b, D, B: ?Sized> Collection for View<'d, 'b, D, B>
where
D: 'd + Datatype,
B: 'b + Pointer,
{
fn count(&self) -> Count {
self.count
}
}
unsafe impl<'d, 'b, D, B: ?Sized> Pointer for View<'d, 'b, D, B>
where
D: 'd + Datatype,
B: 'b + Pointer,
{
fn pointer(&self) -> *const c_void {
self.buffer.pointer()
}
}
unsafe impl<'d, 'b, D, B: ?Sized> Buffer for View<'d, 'b, D, B>
where
D: 'd + Datatype,
B: 'b + Pointer,
{
}
pub struct MutView<'d, 'b, D, B: ?Sized>
where
D: 'd + Datatype,
B: 'b + PointerMut,
{
datatype: &'d D,
count: Count,
buffer: &'b mut B,
}
impl<'d, 'b, D, B: ?Sized> MutView<'d, 'b, D, B>
where
D: 'd + Datatype,
B: 'b + PointerMut,
{
pub unsafe fn with_count_and_datatype(
buffer: &'b mut B,
count: Count,
datatype: &'d D,
) -> MutView<'d, 'b, D, B> {
MutView {
datatype,
count,
buffer,
}
}
}
unsafe impl<'d, 'b, D, B: ?Sized> AsDatatype for MutView<'d, 'b, D, B>
where
D: 'd + Datatype,
B: 'b + PointerMut,
{
type Out = &'d D;
fn as_datatype(&self) -> Self::Out {
self.datatype
}
}
unsafe impl<'d, 'b, D, B: ?Sized> Collection for MutView<'d, 'b, D, B>
where
D: 'd + Datatype,
B: 'b + PointerMut,
{
fn count(&self) -> Count {
self.count
}
}
unsafe impl<'d, 'b, D, B: ?Sized> PointerMut for MutView<'d, 'b, D, B>
where
D: 'd + Datatype,
B: 'b + PointerMut,
{
fn pointer_mut(&mut self) -> *mut c_void {
self.buffer.pointer_mut()
}
}
unsafe impl<'d, 'b, D, B: ?Sized> BufferMut for MutView<'d, 'b, D, B>
where
D: 'd + Datatype,
B: 'b + PointerMut,
{
}
pub trait Partitioned {
fn counts(&self) -> &[Count];
fn displs(&self) -> &[Count];
}
pub trait PartitionedBuffer: Partitioned + Pointer + AsDatatype {}
pub trait PartitionedBufferMut: Partitioned + PointerMut + AsDatatype {}
pub struct Partition<'b, B: 'b + ?Sized, C, D> {
buf: &'b B,
counts: C,
displs: D,
}
impl<'b, B: ?Sized, C, D> Partition<'b, B, C, D>
where
B: 'b + Buffer,
C: Borrow<[Count]>,
D: Borrow<[Count]>,
{
pub fn new(buf: &B, counts: C, displs: D) -> Partition<B, C, D> {
let n = buf.count();
assert!(counts
.borrow()
.iter()
.zip(displs.borrow().iter())
.all(|(&c, &d)| c + d <= n));
Partition {
buf,
counts,
displs,
}
}
}
unsafe impl<'b, B: ?Sized, C, D> AsDatatype for Partition<'b, B, C, D>
where
B: 'b + AsDatatype,
{
type Out = <B as AsDatatype>::Out;
fn as_datatype(&self) -> Self::Out {
self.buf.as_datatype()
}
}
unsafe impl<'b, B: ?Sized, C, D> Pointer for Partition<'b, B, C, D>
where
B: 'b + Pointer,
{
fn pointer(&self) -> *const c_void {
self.buf.pointer()
}
}
impl<'b, B: ?Sized, C, D> Partitioned for Partition<'b, B, C, D>
where
B: 'b,
C: Borrow<[Count]>,
D: Borrow<[Count]>,
{
fn counts(&self) -> &[Count] {
self.counts.borrow()
}
fn displs(&self) -> &[Count] {
self.displs.borrow()
}
}
impl<'b, B: ?Sized, C, D> PartitionedBuffer for Partition<'b, B, C, D>
where
B: 'b + Pointer + AsDatatype,
C: Borrow<[Count]>,
D: Borrow<[Count]>,
{
}
pub struct PartitionMut<'b, B: 'b + ?Sized, C, D> {
buf: &'b mut B,
counts: C,
displs: D,
}
impl<'b, B: ?Sized, C, D> PartitionMut<'b, B, C, D>
where
B: 'b + BufferMut,
C: Borrow<[Count]>,
D: Borrow<[Count]>,
{
pub fn new(buf: &mut B, counts: C, displs: D) -> PartitionMut<B, C, D> {
let n = buf.count();
assert!(counts
.borrow()
.iter()
.zip(displs.borrow().iter())
.all(|(&c, &d)| c + d <= n));
PartitionMut {
buf,
counts,
displs,
}
}
}
unsafe impl<'b, B: ?Sized, C, D> AsDatatype for PartitionMut<'b, B, C, D>
where
B: 'b + AsDatatype,
{
type Out = <B as AsDatatype>::Out;
fn as_datatype(&self) -> Self::Out {
self.buf.as_datatype()
}
}
unsafe impl<'b, B: ?Sized, C, D> PointerMut for PartitionMut<'b, B, C, D>
where
B: 'b + PointerMut,
{
fn pointer_mut(&mut self) -> *mut c_void {
self.buf.pointer_mut()
}
}
impl<'b, B: ?Sized, C, D> Partitioned for PartitionMut<'b, B, C, D>
where
B: 'b,
C: Borrow<[Count]>,
D: Borrow<[Count]>,
{
fn counts(&self) -> &[Count] {
self.counts.borrow()
}
fn displs(&self) -> &[Count] {
self.displs.borrow()
}
}
impl<'b, B: ?Sized, C, D> PartitionedBufferMut for PartitionMut<'b, B, C, D>
where
B: 'b + PointerMut + AsDatatype,
C: Borrow<[Count]>,
D: Borrow<[Count]>,
{
}
pub fn address_of<T>(x: &T) -> Address {
let x: *const T = x;
unsafe { with_uninitialized(|address| ffi::MPI_Get_address(x.cast::<c_void>(), address)).1 }
}