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
extern crate libc;
use libc::{c_int, c_char, c_void};

use std::ptr;
use std::default::Default;

mod constants;
pub use constants::*;
mod types;
pub use types::*;

pub type MpiComm = c_int;
pub type MpiDatatype = c_int;
pub type MpiOp = c_int;

// This, again, seems to only be valid for MPICH.
#[repr(C)]
#[derive(Default)]
pub struct MPI_Status {
    count_lo: c_int,
    count_hi_and_cancelled: c_int,
    mpi_source: c_int,
    mpi_tag: c_int,
    mpi_error: c_int,
}

#[link(name = "mpi")]
extern "C" {
    fn MPI_Init(argc: *const c_int, argv: *const c_char) -> c_int;
    fn MPI_Finalize() -> c_int;
    fn MPI_Comm_rank(comm: MpiComm, rank: *mut c_int) -> c_int;
    fn MPI_Comm_size(comm: MpiComm, size: *mut c_int) -> c_int;
    fn MPI_Send(buf: *const c_void, count: c_int, datatype: MpiDatatype, dest: c_int,
        tag: c_int, comm: MpiComm) -> c_int;
    fn MPI_Recv(buf: *mut c_void, count: c_int, datatype: MpiDatatype, source: c_int,
        tag: c_int, comm: MpiComm, status: *mut MPI_Status) -> c_int;
}

pub fn mpi_init() -> i32 {
    unsafe {
        let argc = ptr::null();
        let argv = ptr::null();
        let ret = MPI_Init(argc, argv);
        return ret;
    }
}

pub fn mpi_finalize() -> i32 {
    unsafe {
        let ret = MPI_Finalize();
        return ret;
    }
}

pub fn mpi_comm_rank(comm: MpiComm, rank: *mut i32) -> i32 {
    unsafe {
        let c_comm:MpiComm = comm as MpiComm;
        let ret: i32 = MPI_Comm_rank(c_comm, rank);
        return ret;
    }
}

pub fn mpi_comm_size(comm: MpiComm, size: *mut i32) -> i32 {
    unsafe {
        let c_comm:MpiComm = comm as MpiComm;
        let ret: i32 = MPI_Comm_size(c_comm, size);
        return ret;
    }
}

pub fn mpi_send_scalar<T: MpiType>(buf: &T, dest: i32, tag: i32, comm: MpiComm) -> i32 {
    unsafe {
        let c_buf: *const c_void = buf as *const _ as *const c_void;
        let count = 1;
        let mpi_type = buf.get_mpi_type();
        let ret: i32 = MPI_Send(c_buf, count, mpi_type, dest, tag, comm);
        return ret;
    }
}

pub fn mpi_send_slice<T: MpiType + Default>(buf: &[T], dest: i32, tag: i32, comm: MpiComm) -> i32 {
    unsafe {
        let c_buf: *const c_void = buf.as_ptr() as *const c_void;
        let count = buf.len() as i32;
        // Meh, a bit of a faff. Better than getting 0th value since count may be 0.
        let array_type: T = Default::default();
        let mpi_type = array_type.get_mpi_type();
        let ret: i32 = MPI_Send(c_buf, count, mpi_type, dest, tag, comm);
        return ret;
    }
}

pub fn mpi_recv_scalar<T: MpiType>(buf: &mut T, dest: i32, tag: i32, comm: MpiComm) -> i32 {
    unsafe {
        let mut status: MPI_Status = Default::default();
        let c_buf: *mut c_void = buf as *mut _ as *mut c_void;
        let count = 1;
        let mpi_type = buf.get_mpi_type();
        let ret: i32 = MPI_Recv(c_buf, count, mpi_type, dest, tag, comm, &mut status);
        return ret;
    }
}

pub fn mpi_recv_slice<T: MpiType + Default>(buf: &mut [T], dest: i32, tag: i32, comm: MpiComm) -> i32 {
    unsafe {
        let mut status: MPI_Status = Default::default();
        let c_buf: *mut c_void = buf.as_ptr() as *mut c_void;
        let count = buf.len() as i32;
        // Meh, a bit of a faff. Better than getting 0th value since count may be 0.
        let array_type: T = Default::default();
        let mpi_type = array_type.get_mpi_type();
        let ret: i32 = MPI_Recv(c_buf, count, mpi_type, dest, tag, comm, &mut status);
        return ret;
    }
}

#[cfg(test)]
mod test;