use std::{
ops::{Deref, DerefMut},
os::raw::c_char,
};
use crate::prelude::*;
#[derive(Debug, Clone, Copy)]
pub enum VectorOpt<'a> {
Some(&'a Vector<'a>),
Active,
None,
}
impl<'a> From<&'a Vector<'_>> for VectorOpt<'a> {
fn from(vec: &'a Vector) -> Self {
debug_assert!(vec.ptr != unsafe { bind_ceed::CEED_VECTOR_NONE });
debug_assert!(vec.ptr != unsafe { bind_ceed::CEED_VECTOR_ACTIVE });
Self::Some(vec)
}
}
impl<'a> VectorOpt<'a> {
pub(crate) fn to_raw(self) -> bind_ceed::CeedVector {
match self {
Self::Some(vec) => vec.ptr,
Self::None => unsafe { bind_ceed::CEED_VECTOR_NONE },
Self::Active => unsafe { bind_ceed::CEED_VECTOR_ACTIVE },
}
}
}
#[derive(Debug)]
pub struct Vector<'a> {
ceed: &'a crate::Ceed,
pub(crate) ptr: bind_ceed::CeedVector,
}
impl From<&'_ Vector<'_>> for bind_ceed::CeedVector {
fn from(vec: &Vector) -> Self {
vec.ptr
}
}
impl<'a> Drop for Vector<'a> {
fn drop(&mut self) {
let not_none_and_active = self.ptr != unsafe { bind_ceed::CEED_VECTOR_NONE }
&& self.ptr != unsafe { bind_ceed::CEED_VECTOR_ACTIVE };
if not_none_and_active {
unsafe { bind_ceed::CeedVectorDestroy(&mut self.ptr) };
}
}
}
impl<'a> fmt::Display for Vector<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut ptr = std::ptr::null_mut();
let mut sizeloc = crate::MAX_BUFFER_LENGTH;
let format = CString::new("%12.8f").expect("CString::new failed");
let format_c: *const c_char = format.into_raw();
let cstring = unsafe {
let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc);
bind_ceed::CeedVectorView(self.ptr, format_c, file);
bind_ceed::fclose(file);
CString::from_raw(ptr)
};
cstring.to_string_lossy().fmt(f)
}
}
impl<'a> Vector<'a> {
pub fn create(ceed: &'a crate::Ceed, n: usize) -> crate::Result<Self> {
let n = i32::try_from(n).unwrap();
let mut ptr = std::ptr::null_mut();
let ierr = unsafe { bind_ceed::CeedVectorCreate(ceed.ptr, n, &mut ptr) };
ceed.check_error(ierr)?;
Ok(Self { ceed, ptr })
}
pub(crate) fn from_raw(
ceed: &'a crate::Ceed,
ptr: bind_ceed::CeedVector,
) -> crate::Result<Self> {
Ok(Self { ceed, ptr })
}
pub fn from_slice(ceed: &'a crate::Ceed, v: &[f64]) -> crate::Result<Self> {
let mut x = Self::create(ceed, v.len())?;
x.set_slice(v)?;
Ok(x)
}
pub fn from_array(ceed: &'a crate::Ceed, v: &mut [f64]) -> crate::Result<Self> {
let x = Self::create(ceed, v.len())?;
let (host, user_pointer) = (
crate::MemType::Host as bind_ceed::CeedMemType,
crate::CopyMode::UsePointer as bind_ceed::CeedCopyMode,
);
let v = v.as_ptr() as *mut f64;
let ierr = unsafe { bind_ceed::CeedVectorSetArray(x.ptr, host, user_pointer, v) };
ceed.check_error(ierr)?;
Ok(x)
}
pub fn length(&self) -> usize {
let mut n = 0;
unsafe { bind_ceed::CeedVectorGetLength(self.ptr, &mut n) };
usize::try_from(n).unwrap()
}
pub fn len(&self) -> usize {
self.length()
}
pub fn set_value(&mut self, value: f64) -> crate::Result<i32> {
let ierr = unsafe { bind_ceed::CeedVectorSetValue(self.ptr, value) };
self.ceed.check_error(ierr)
}
pub fn set_slice(&mut self, slice: &[f64]) -> crate::Result<i32> {
assert_eq!(self.length(), slice.len());
let (host, copy_mode) = (
crate::MemType::Host as bind_ceed::CeedMemType,
crate::CopyMode::CopyValues as bind_ceed::CeedCopyMode,
);
let ierr = unsafe {
bind_ceed::CeedVectorSetArray(self.ptr, host, copy_mode, slice.as_ptr() as *mut f64)
};
self.ceed.check_error(ierr)
}
pub fn sync(&self, mtype: crate::MemType) -> crate::Result<i32> {
let ierr =
unsafe { bind_ceed::CeedVectorSyncArray(self.ptr, mtype as bind_ceed::CeedMemType) };
self.ceed.check_error(ierr)
}
pub fn view(&self) -> VectorView {
VectorView::new(self)
}
pub fn view_mut(&mut self) -> VectorViewMut {
VectorViewMut::new(self)
}
pub fn norm(&self, ntype: crate::NormType) -> crate::Result<f64> {
let mut res: f64 = 0.0;
let ierr = unsafe {
bind_ceed::CeedVectorNorm(self.ptr, ntype as bind_ceed::CeedNormType, &mut res)
};
self.ceed.check_error(ierr)?;
Ok(res)
}
#[allow(unused_mut)]
pub fn scale(mut self, alpha: f64) -> crate::Result<Self> {
let ierr = unsafe { bind_ceed::CeedVectorScale(self.ptr, alpha) };
self.ceed.check_error(ierr)?;
Ok(self)
}
#[allow(unused_mut)]
pub fn axpy(mut self, alpha: f64, x: &crate::Vector) -> crate::Result<Self> {
let ierr = unsafe { bind_ceed::CeedVectorAXPY(self.ptr, alpha, x.ptr) };
self.ceed.check_error(ierr)?;
Ok(self)
}
#[allow(unused_mut)]
pub fn pointwise_mult(mut self, x: &crate::Vector, y: &crate::Vector) -> crate::Result<Self> {
let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, x.ptr, y.ptr) };
self.ceed.check_error(ierr)?;
Ok(self)
}
#[allow(unused_mut)]
pub fn pointwise_scale(mut self, x: &crate::Vector) -> crate::Result<Self> {
let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, self.ptr, x.ptr) };
self.ceed.check_error(ierr)?;
Ok(self)
}
#[allow(unused_mut)]
pub fn pointwise_square(mut self) -> crate::Result<Self> {
let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, self.ptr, self.ptr) };
self.ceed.check_error(ierr)?;
Ok(self)
}
}
#[derive(Debug)]
pub struct VectorView<'a> {
vec: &'a Vector<'a>,
array: *const f64,
}
impl<'a> VectorView<'a> {
fn new(vec: &'a Vector) -> Self {
let mut array = std::ptr::null();
unsafe {
bind_ceed::CeedVectorGetArrayRead(
vec.ptr,
crate::MemType::Host as bind_ceed::CeedMemType,
&mut array,
);
}
Self {
vec: vec,
array: array,
}
}
}
impl<'a> Drop for VectorView<'a> {
fn drop(&mut self) {
unsafe {
bind_ceed::CeedVectorRestoreArrayRead(self.vec.ptr, &mut self.array);
}
}
}
impl<'a> Deref for VectorView<'a> {
type Target = [f64];
fn deref(&self) -> &[f64] {
unsafe { std::slice::from_raw_parts(self.array, self.vec.len()) }
}
}
impl<'a> fmt::Display for VectorView<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "VectorView({:?})", self.deref())
}
}
#[derive(Debug)]
pub struct VectorViewMut<'a> {
vec: &'a Vector<'a>,
array: *mut f64,
}
impl<'a> VectorViewMut<'a> {
fn new(vec: &'a mut Vector) -> Self {
let mut ptr = std::ptr::null_mut();
unsafe {
bind_ceed::CeedVectorGetArray(
vec.ptr,
crate::MemType::Host as bind_ceed::CeedMemType,
&mut ptr,
);
}
Self {
vec: vec,
array: ptr,
}
}
}
impl<'a> Drop for VectorViewMut<'a> {
fn drop(&mut self) {
unsafe {
bind_ceed::CeedVectorRestoreArray(self.vec.ptr, &mut self.array);
}
}
}
impl<'a> Deref for VectorViewMut<'a> {
type Target = [f64];
fn deref(&self) -> &[f64] {
unsafe { std::slice::from_raw_parts(self.array, self.vec.len()) }
}
}
impl<'a> DerefMut for VectorViewMut<'a> {
fn deref_mut(&mut self) -> &mut [f64] {
unsafe { std::slice::from_raw_parts_mut(self.array, self.vec.len()) }
}
}
impl<'a> fmt::Display for VectorViewMut<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "VectorViewMut({:?})", self.deref())
}
}