xref: /libCEED/rust/libceed/src/vector.rs (revision 9df49d7ef0a77c7a3baec2427d8a7274681409b6)
1*9df49d7eSJed Brown // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2*9df49d7eSJed Brown // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3*9df49d7eSJed Brown // reserved. See files LICENSE and NOTICE for details.
4*9df49d7eSJed Brown //
5*9df49d7eSJed Brown // This file is part of CEED, a collection of benchmarks, miniapps, software
6*9df49d7eSJed Brown // libraries and APIs for efficient high-order finite element and spectral
7*9df49d7eSJed Brown // element discretizations for exascale applications. For more information and
8*9df49d7eSJed Brown // source code availability see http://github.com/ceed.
9*9df49d7eSJed Brown //
10*9df49d7eSJed Brown // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11*9df49d7eSJed Brown // a collaborative effort of two U.S. Department of Energy organizations (Office
12*9df49d7eSJed Brown // of Science and the National Nuclear Security Administration) responsible for
13*9df49d7eSJed Brown // the planning and preparation of a capable exascale ecosystem, including
14*9df49d7eSJed Brown // software, applications, hardware, advanced system engineering and early
15*9df49d7eSJed Brown // testbed platforms, in support of the nation's exascale computing imperative
16*9df49d7eSJed Brown 
17*9df49d7eSJed Brown //! A Ceed Vector constitutes the main data structure and serves as input/output
18*9df49d7eSJed Brown //! for Ceed Operators.
19*9df49d7eSJed Brown 
20*9df49d7eSJed Brown use std::{
21*9df49d7eSJed Brown     ops::{Deref, DerefMut},
22*9df49d7eSJed Brown     os::raw::c_char,
23*9df49d7eSJed Brown };
24*9df49d7eSJed Brown 
25*9df49d7eSJed Brown use crate::prelude::*;
26*9df49d7eSJed Brown 
27*9df49d7eSJed Brown // -----------------------------------------------------------------------------
28*9df49d7eSJed Brown // CeedVector option
29*9df49d7eSJed Brown // -----------------------------------------------------------------------------
30*9df49d7eSJed Brown #[derive(Debug, Clone, Copy)]
31*9df49d7eSJed Brown pub enum VectorOpt<'a> {
32*9df49d7eSJed Brown     Some(&'a Vector<'a>),
33*9df49d7eSJed Brown     Active,
34*9df49d7eSJed Brown     None,
35*9df49d7eSJed Brown }
36*9df49d7eSJed Brown /// Construct a VectorOpt reference from a Vector reference
37*9df49d7eSJed Brown impl<'a> From<&'a Vector<'_>> for VectorOpt<'a> {
38*9df49d7eSJed Brown     fn from(vec: &'a Vector) -> Self {
39*9df49d7eSJed Brown         debug_assert!(vec.ptr != unsafe { bind_ceed::CEED_VECTOR_NONE });
40*9df49d7eSJed Brown         debug_assert!(vec.ptr != unsafe { bind_ceed::CEED_VECTOR_ACTIVE });
41*9df49d7eSJed Brown         Self::Some(vec)
42*9df49d7eSJed Brown     }
43*9df49d7eSJed Brown }
44*9df49d7eSJed Brown impl<'a> VectorOpt<'a> {
45*9df49d7eSJed Brown     /// Transform a Rust libCEED VectorOpt into C libCEED CeedVector
46*9df49d7eSJed Brown     pub(crate) fn to_raw(self) -> bind_ceed::CeedVector {
47*9df49d7eSJed Brown         match self {
48*9df49d7eSJed Brown             Self::Some(vec) => vec.ptr,
49*9df49d7eSJed Brown             Self::None => unsafe { bind_ceed::CEED_VECTOR_NONE },
50*9df49d7eSJed Brown             Self::Active => unsafe { bind_ceed::CEED_VECTOR_ACTIVE },
51*9df49d7eSJed Brown         }
52*9df49d7eSJed Brown     }
53*9df49d7eSJed Brown }
54*9df49d7eSJed Brown 
55*9df49d7eSJed Brown // -----------------------------------------------------------------------------
56*9df49d7eSJed Brown // CeedVector context wrapper
57*9df49d7eSJed Brown // -----------------------------------------------------------------------------
58*9df49d7eSJed Brown #[derive(Debug)]
59*9df49d7eSJed Brown pub struct Vector<'a> {
60*9df49d7eSJed Brown     ceed: &'a crate::Ceed,
61*9df49d7eSJed Brown     pub(crate) ptr: bind_ceed::CeedVector,
62*9df49d7eSJed Brown }
63*9df49d7eSJed Brown impl From<&'_ Vector<'_>> for bind_ceed::CeedVector {
64*9df49d7eSJed Brown     fn from(vec: &Vector) -> Self {
65*9df49d7eSJed Brown         vec.ptr
66*9df49d7eSJed Brown     }
67*9df49d7eSJed Brown }
68*9df49d7eSJed Brown 
69*9df49d7eSJed Brown // -----------------------------------------------------------------------------
70*9df49d7eSJed Brown // Destructor
71*9df49d7eSJed Brown // -----------------------------------------------------------------------------
72*9df49d7eSJed Brown impl<'a> Drop for Vector<'a> {
73*9df49d7eSJed Brown     fn drop(&mut self) {
74*9df49d7eSJed Brown         let not_none_and_active = self.ptr != unsafe { bind_ceed::CEED_VECTOR_NONE }
75*9df49d7eSJed Brown             && self.ptr != unsafe { bind_ceed::CEED_VECTOR_ACTIVE };
76*9df49d7eSJed Brown 
77*9df49d7eSJed Brown         if not_none_and_active {
78*9df49d7eSJed Brown             unsafe { bind_ceed::CeedVectorDestroy(&mut self.ptr) };
79*9df49d7eSJed Brown         }
80*9df49d7eSJed Brown     }
81*9df49d7eSJed Brown }
82*9df49d7eSJed Brown 
83*9df49d7eSJed Brown // -----------------------------------------------------------------------------
84*9df49d7eSJed Brown // Display
85*9df49d7eSJed Brown // -----------------------------------------------------------------------------
86*9df49d7eSJed Brown impl<'a> fmt::Display for Vector<'a> {
87*9df49d7eSJed Brown     /// View a Vector
88*9df49d7eSJed Brown     ///
89*9df49d7eSJed Brown     /// ```
90*9df49d7eSJed Brown     /// # use libceed::prelude::*;
91*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
92*9df49d7eSJed Brown     /// let vec = libceed::vector::Vector::from_slice(&ceed, &[1., 2., 3.]).unwrap();
93*9df49d7eSJed Brown     /// assert_eq!(
94*9df49d7eSJed Brown     ///     vec.to_string(),
95*9df49d7eSJed Brown     ///     "CeedVector length 3
96*9df49d7eSJed Brown     ///     1.00000000
97*9df49d7eSJed Brown     ///     2.00000000
98*9df49d7eSJed Brown     ///     3.00000000
99*9df49d7eSJed Brown     /// "
100*9df49d7eSJed Brown     /// )
101*9df49d7eSJed Brown     /// ```
102*9df49d7eSJed Brown     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103*9df49d7eSJed Brown         let mut ptr = std::ptr::null_mut();
104*9df49d7eSJed Brown         let mut sizeloc = crate::MAX_BUFFER_LENGTH;
105*9df49d7eSJed Brown         let format = CString::new("%12.8f").expect("CString::new failed");
106*9df49d7eSJed Brown         let format_c: *const c_char = format.into_raw();
107*9df49d7eSJed Brown         let cstring = unsafe {
108*9df49d7eSJed Brown             let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc);
109*9df49d7eSJed Brown             bind_ceed::CeedVectorView(self.ptr, format_c, file);
110*9df49d7eSJed Brown             bind_ceed::fclose(file);
111*9df49d7eSJed Brown             CString::from_raw(ptr)
112*9df49d7eSJed Brown         };
113*9df49d7eSJed Brown         cstring.to_string_lossy().fmt(f)
114*9df49d7eSJed Brown     }
115*9df49d7eSJed Brown }
116*9df49d7eSJed Brown 
117*9df49d7eSJed Brown // -----------------------------------------------------------------------------
118*9df49d7eSJed Brown // Implementations
119*9df49d7eSJed Brown // -----------------------------------------------------------------------------
120*9df49d7eSJed Brown impl<'a> Vector<'a> {
121*9df49d7eSJed Brown     // Constructors
122*9df49d7eSJed Brown     pub fn create(ceed: &'a crate::Ceed, n: usize) -> crate::Result<Self> {
123*9df49d7eSJed Brown         let n = i32::try_from(n).unwrap();
124*9df49d7eSJed Brown         let mut ptr = std::ptr::null_mut();
125*9df49d7eSJed Brown         let ierr = unsafe { bind_ceed::CeedVectorCreate(ceed.ptr, n, &mut ptr) };
126*9df49d7eSJed Brown         ceed.check_error(ierr)?;
127*9df49d7eSJed Brown         Ok(Self { ceed, ptr })
128*9df49d7eSJed Brown     }
129*9df49d7eSJed Brown 
130*9df49d7eSJed Brown     pub(crate) fn from_raw(
131*9df49d7eSJed Brown         ceed: &'a crate::Ceed,
132*9df49d7eSJed Brown         ptr: bind_ceed::CeedVector,
133*9df49d7eSJed Brown     ) -> crate::Result<Self> {
134*9df49d7eSJed Brown         Ok(Self { ceed, ptr })
135*9df49d7eSJed Brown     }
136*9df49d7eSJed Brown 
137*9df49d7eSJed Brown     /// Create a Vector from a slice
138*9df49d7eSJed Brown     ///
139*9df49d7eSJed Brown     /// # arguments
140*9df49d7eSJed Brown     ///
141*9df49d7eSJed Brown     /// * `slice` - values to initialize vector with
142*9df49d7eSJed Brown     ///
143*9df49d7eSJed Brown     /// ```
144*9df49d7eSJed Brown     /// # use libceed::prelude::*;
145*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
146*9df49d7eSJed Brown     /// let vec = vector::Vector::from_slice(&ceed, &[1., 2., 3.]).unwrap();
147*9df49d7eSJed Brown     /// assert_eq!(vec.length(), 3, "Incorrect length from slice");
148*9df49d7eSJed Brown     /// ```
149*9df49d7eSJed Brown     pub fn from_slice(ceed: &'a crate::Ceed, v: &[f64]) -> crate::Result<Self> {
150*9df49d7eSJed Brown         let mut x = Self::create(ceed, v.len())?;
151*9df49d7eSJed Brown         x.set_slice(v)?;
152*9df49d7eSJed Brown         Ok(x)
153*9df49d7eSJed Brown     }
154*9df49d7eSJed Brown 
155*9df49d7eSJed Brown     /// Create a Vector from a mutable array reference
156*9df49d7eSJed Brown     ///
157*9df49d7eSJed Brown     /// # arguments
158*9df49d7eSJed Brown     ///
159*9df49d7eSJed Brown     /// * `slice` - values to initialize vector with
160*9df49d7eSJed Brown     ///
161*9df49d7eSJed Brown     /// ```
162*9df49d7eSJed Brown     /// # use libceed::prelude::*;
163*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
164*9df49d7eSJed Brown     /// let mut rust_vec = vec![1., 2., 3.];
165*9df49d7eSJed Brown     /// let vec = libceed::vector::Vector::from_array(&ceed, &mut rust_vec).unwrap();
166*9df49d7eSJed Brown     ///
167*9df49d7eSJed Brown     /// assert_eq!(vec.length(), 3, "Incorrect length from slice");
168*9df49d7eSJed Brown     /// ```
169*9df49d7eSJed Brown     pub fn from_array(ceed: &'a crate::Ceed, v: &mut [f64]) -> crate::Result<Self> {
170*9df49d7eSJed Brown         let x = Self::create(ceed, v.len())?;
171*9df49d7eSJed Brown         let (host, user_pointer) = (
172*9df49d7eSJed Brown             crate::MemType::Host as bind_ceed::CeedMemType,
173*9df49d7eSJed Brown             crate::CopyMode::UsePointer as bind_ceed::CeedCopyMode,
174*9df49d7eSJed Brown         );
175*9df49d7eSJed Brown         let v = v.as_ptr() as *mut f64;
176*9df49d7eSJed Brown         let ierr = unsafe { bind_ceed::CeedVectorSetArray(x.ptr, host, user_pointer, v) };
177*9df49d7eSJed Brown         ceed.check_error(ierr)?;
178*9df49d7eSJed Brown         Ok(x)
179*9df49d7eSJed Brown     }
180*9df49d7eSJed Brown 
181*9df49d7eSJed Brown     /// Returns the length of a CeedVector
182*9df49d7eSJed Brown     ///
183*9df49d7eSJed Brown     /// ```
184*9df49d7eSJed Brown     /// # use libceed::prelude::*;
185*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
186*9df49d7eSJed Brown     /// let vec = ceed.vector(10).unwrap();
187*9df49d7eSJed Brown     ///
188*9df49d7eSJed Brown     /// let n = vec.length();
189*9df49d7eSJed Brown     /// assert_eq!(n, 10, "Incorrect length");
190*9df49d7eSJed Brown     /// ```
191*9df49d7eSJed Brown     pub fn length(&self) -> usize {
192*9df49d7eSJed Brown         let mut n = 0;
193*9df49d7eSJed Brown         unsafe { bind_ceed::CeedVectorGetLength(self.ptr, &mut n) };
194*9df49d7eSJed Brown         usize::try_from(n).unwrap()
195*9df49d7eSJed Brown     }
196*9df49d7eSJed Brown 
197*9df49d7eSJed Brown     /// Returns the length of a CeedVector
198*9df49d7eSJed Brown     ///
199*9df49d7eSJed Brown     /// ```
200*9df49d7eSJed Brown     /// # use libceed::prelude::*;
201*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
202*9df49d7eSJed Brown     /// let vec = ceed.vector(10).unwrap();
203*9df49d7eSJed Brown     /// assert_eq!(vec.len(), 10, "Incorrect length");
204*9df49d7eSJed Brown     /// ```
205*9df49d7eSJed Brown     pub fn len(&self) -> usize {
206*9df49d7eSJed Brown         self.length()
207*9df49d7eSJed Brown     }
208*9df49d7eSJed Brown 
209*9df49d7eSJed Brown     /// Set the CeedVector to a constant value
210*9df49d7eSJed Brown     ///
211*9df49d7eSJed Brown     /// # arguments
212*9df49d7eSJed Brown     ///
213*9df49d7eSJed Brown     /// * `val` - Value to be used
214*9df49d7eSJed Brown     ///
215*9df49d7eSJed Brown     /// ```
216*9df49d7eSJed Brown     /// # use libceed::prelude::*;
217*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
218*9df49d7eSJed Brown     /// let len = 10;
219*9df49d7eSJed Brown     /// let mut vec = ceed.vector(len).unwrap();
220*9df49d7eSJed Brown     ///
221*9df49d7eSJed Brown     /// let val = 42.0;
222*9df49d7eSJed Brown     /// vec.set_value(val).unwrap();
223*9df49d7eSJed Brown     ///
224*9df49d7eSJed Brown     /// vec.view().iter().for_each(|v| {
225*9df49d7eSJed Brown     ///     assert_eq!(*v, val, "Value not set correctly");
226*9df49d7eSJed Brown     /// });
227*9df49d7eSJed Brown     /// ```
228*9df49d7eSJed Brown     pub fn set_value(&mut self, value: f64) -> crate::Result<i32> {
229*9df49d7eSJed Brown         let ierr = unsafe { bind_ceed::CeedVectorSetValue(self.ptr, value) };
230*9df49d7eSJed Brown         self.ceed.check_error(ierr)
231*9df49d7eSJed Brown     }
232*9df49d7eSJed Brown 
233*9df49d7eSJed Brown     /// Set values from a slice of the same length
234*9df49d7eSJed Brown     ///
235*9df49d7eSJed Brown     /// # arguments
236*9df49d7eSJed Brown     ///
237*9df49d7eSJed Brown     /// * `slice` - values to into self; length must match
238*9df49d7eSJed Brown     ///
239*9df49d7eSJed Brown     /// ```
240*9df49d7eSJed Brown     /// # use libceed::prelude::*;
241*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
242*9df49d7eSJed Brown     /// let mut vec = ceed.vector(4).unwrap();
243*9df49d7eSJed Brown     /// vec.set_slice(&[10., 11., 12., 13.]).unwrap();
244*9df49d7eSJed Brown     ///
245*9df49d7eSJed Brown     /// vec.view().iter().enumerate().for_each(|(i, v)| {
246*9df49d7eSJed Brown     ///     assert_eq!(*v, 10. + i as f64, "Slice not set correctly");
247*9df49d7eSJed Brown     /// });
248*9df49d7eSJed Brown     /// ```
249*9df49d7eSJed Brown     pub fn set_slice(&mut self, slice: &[f64]) -> crate::Result<i32> {
250*9df49d7eSJed Brown         assert_eq!(self.length(), slice.len());
251*9df49d7eSJed Brown         let (host, copy_mode) = (
252*9df49d7eSJed Brown             crate::MemType::Host as bind_ceed::CeedMemType,
253*9df49d7eSJed Brown             crate::CopyMode::CopyValues as bind_ceed::CeedCopyMode,
254*9df49d7eSJed Brown         );
255*9df49d7eSJed Brown         let ierr = unsafe {
256*9df49d7eSJed Brown             bind_ceed::CeedVectorSetArray(self.ptr, host, copy_mode, slice.as_ptr() as *mut f64)
257*9df49d7eSJed Brown         };
258*9df49d7eSJed Brown         self.ceed.check_error(ierr)
259*9df49d7eSJed Brown     }
260*9df49d7eSJed Brown 
261*9df49d7eSJed Brown     /// Sync the CeedVector to a specified memtype
262*9df49d7eSJed Brown     ///
263*9df49d7eSJed Brown     /// # arguments
264*9df49d7eSJed Brown     ///
265*9df49d7eSJed Brown     /// * `mtype` - Memtype to be synced
266*9df49d7eSJed Brown     ///
267*9df49d7eSJed Brown     /// ```
268*9df49d7eSJed Brown     /// # use libceed::prelude::*;
269*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
270*9df49d7eSJed Brown     /// let len = 10;
271*9df49d7eSJed Brown     /// let mut vec = ceed.vector(len).unwrap();
272*9df49d7eSJed Brown     ///
273*9df49d7eSJed Brown     /// let val = 42.0;
274*9df49d7eSJed Brown     /// vec.set_value(val);
275*9df49d7eSJed Brown     /// vec.sync(MemType::Host).unwrap();
276*9df49d7eSJed Brown     ///
277*9df49d7eSJed Brown     /// vec.view().iter().for_each(|v| {
278*9df49d7eSJed Brown     ///     assert_eq!(*v, val, "Value not set correctly");
279*9df49d7eSJed Brown     /// });
280*9df49d7eSJed Brown     /// ```
281*9df49d7eSJed Brown     pub fn sync(&self, mtype: crate::MemType) -> crate::Result<i32> {
282*9df49d7eSJed Brown         let ierr =
283*9df49d7eSJed Brown             unsafe { bind_ceed::CeedVectorSyncArray(self.ptr, mtype as bind_ceed::CeedMemType) };
284*9df49d7eSJed Brown         self.ceed.check_error(ierr)
285*9df49d7eSJed Brown     }
286*9df49d7eSJed Brown 
287*9df49d7eSJed Brown     /// Create an immutable view
288*9df49d7eSJed Brown     ///
289*9df49d7eSJed Brown     /// ```
290*9df49d7eSJed Brown     /// # use libceed::prelude::*;
291*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
292*9df49d7eSJed Brown     /// let vec = ceed.vector_from_slice(&[10., 11., 12., 13.]).unwrap();
293*9df49d7eSJed Brown     ///
294*9df49d7eSJed Brown     /// let v = vec.view();
295*9df49d7eSJed Brown     /// assert_eq!(v[0..2], [10., 11.]);
296*9df49d7eSJed Brown     ///
297*9df49d7eSJed Brown     /// // It is valid to have multiple immutable views
298*9df49d7eSJed Brown     /// let w = vec.view();
299*9df49d7eSJed Brown     /// assert_eq!(v[1..], w[1..]);
300*9df49d7eSJed Brown     /// ```
301*9df49d7eSJed Brown     pub fn view(&self) -> VectorView {
302*9df49d7eSJed Brown         VectorView::new(self)
303*9df49d7eSJed Brown     }
304*9df49d7eSJed Brown 
305*9df49d7eSJed Brown     /// Create an mutable view
306*9df49d7eSJed Brown     ///
307*9df49d7eSJed Brown     /// ```
308*9df49d7eSJed Brown     /// # use libceed::prelude::*;
309*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
310*9df49d7eSJed Brown     /// let mut vec = ceed.vector_from_slice(&[10., 11., 12., 13.]).unwrap();
311*9df49d7eSJed Brown     ///
312*9df49d7eSJed Brown     /// {
313*9df49d7eSJed Brown     ///     let mut v = vec.view_mut();
314*9df49d7eSJed Brown     ///     v[2] = 9.;
315*9df49d7eSJed Brown     /// }
316*9df49d7eSJed Brown     ///
317*9df49d7eSJed Brown     /// let w = vec.view();
318*9df49d7eSJed Brown     /// assert_eq!(w[2], 9., "View did not mutate data");
319*9df49d7eSJed Brown     /// ```
320*9df49d7eSJed Brown     pub fn view_mut(&mut self) -> VectorViewMut {
321*9df49d7eSJed Brown         VectorViewMut::new(self)
322*9df49d7eSJed Brown     }
323*9df49d7eSJed Brown 
324*9df49d7eSJed Brown     /// Return the norm of a CeedVector
325*9df49d7eSJed Brown     ///
326*9df49d7eSJed Brown     /// # arguments
327*9df49d7eSJed Brown     ///
328*9df49d7eSJed Brown     /// * `ntype` - Norm type One, Two, or Max
329*9df49d7eSJed Brown     ///
330*9df49d7eSJed Brown     /// ```
331*9df49d7eSJed Brown     /// # use libceed::prelude::*;
332*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
333*9df49d7eSJed Brown     /// let vec = ceed.vector_from_slice(&[1., 2., 3., 4.]).unwrap();
334*9df49d7eSJed Brown     ///
335*9df49d7eSJed Brown     /// let max_norm = vec.norm(NormType::Max).unwrap();
336*9df49d7eSJed Brown     /// assert_eq!(max_norm, 4.0, "Incorrect Max norm");
337*9df49d7eSJed Brown     ///
338*9df49d7eSJed Brown     /// let l1_norm = vec.norm(NormType::One).unwrap();
339*9df49d7eSJed Brown     /// assert_eq!(l1_norm, 10., "Incorrect L1 norm");
340*9df49d7eSJed Brown     ///
341*9df49d7eSJed Brown     /// let l2_norm = vec.norm(NormType::Two).unwrap();
342*9df49d7eSJed Brown     /// assert!((l2_norm - 5.477) < 1e-3, "Incorrect L2 norm");
343*9df49d7eSJed Brown     /// ```
344*9df49d7eSJed Brown     pub fn norm(&self, ntype: crate::NormType) -> crate::Result<f64> {
345*9df49d7eSJed Brown         let mut res: f64 = 0.0;
346*9df49d7eSJed Brown         let ierr = unsafe {
347*9df49d7eSJed Brown             bind_ceed::CeedVectorNorm(self.ptr, ntype as bind_ceed::CeedNormType, &mut res)
348*9df49d7eSJed Brown         };
349*9df49d7eSJed Brown         self.ceed.check_error(ierr)?;
350*9df49d7eSJed Brown         Ok(res)
351*9df49d7eSJed Brown     }
352*9df49d7eSJed Brown 
353*9df49d7eSJed Brown     /// Compute x = alpha x for a CeedVector
354*9df49d7eSJed Brown     ///
355*9df49d7eSJed Brown     /// # arguments
356*9df49d7eSJed Brown     ///
357*9df49d7eSJed Brown     /// * `alpha` - scaling factor
358*9df49d7eSJed Brown     ///
359*9df49d7eSJed Brown     /// ```
360*9df49d7eSJed Brown     /// # use libceed::prelude::*;
361*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
362*9df49d7eSJed Brown     /// let mut vec = ceed.vector_from_slice(&[0., 1., 2., 3., 4.]).unwrap();
363*9df49d7eSJed Brown     ///
364*9df49d7eSJed Brown     /// vec = vec.scale(-1.0).unwrap();
365*9df49d7eSJed Brown     /// vec.view().iter().enumerate().for_each(|(i, &v)| {
366*9df49d7eSJed Brown     ///     assert_eq!(v, -(i as f64), "Value not set correctly");
367*9df49d7eSJed Brown     /// });
368*9df49d7eSJed Brown     /// ```
369*9df49d7eSJed Brown     #[allow(unused_mut)]
370*9df49d7eSJed Brown     pub fn scale(mut self, alpha: f64) -> crate::Result<Self> {
371*9df49d7eSJed Brown         let ierr = unsafe { bind_ceed::CeedVectorScale(self.ptr, alpha) };
372*9df49d7eSJed Brown         self.ceed.check_error(ierr)?;
373*9df49d7eSJed Brown         Ok(self)
374*9df49d7eSJed Brown     }
375*9df49d7eSJed Brown 
376*9df49d7eSJed Brown     /// Compute y = alpha x + y for a pair of CeedVectors
377*9df49d7eSJed Brown     ///
378*9df49d7eSJed Brown     /// # arguments
379*9df49d7eSJed Brown     ///
380*9df49d7eSJed Brown     /// * `alpha` - scaling factor
381*9df49d7eSJed Brown     /// * `x`     - second vector, must be different than self
382*9df49d7eSJed Brown     ///
383*9df49d7eSJed Brown     /// ```
384*9df49d7eSJed Brown     /// # use libceed::prelude::*;
385*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
386*9df49d7eSJed Brown     /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.]).unwrap();
387*9df49d7eSJed Brown     /// let mut y = ceed.vector_from_slice(&[0., 1., 2., 3., 4.]).unwrap();
388*9df49d7eSJed Brown     ///
389*9df49d7eSJed Brown     /// y = y.axpy(-0.5, &x).unwrap();
390*9df49d7eSJed Brown     /// y.view().iter().enumerate().for_each(|(i, &v)| {
391*9df49d7eSJed Brown     ///     assert_eq!(v, (i as f64) / 2.0, "Value not set correctly");
392*9df49d7eSJed Brown     /// });
393*9df49d7eSJed Brown     /// ```
394*9df49d7eSJed Brown     #[allow(unused_mut)]
395*9df49d7eSJed Brown     pub fn axpy(mut self, alpha: f64, x: &crate::Vector) -> crate::Result<Self> {
396*9df49d7eSJed Brown         let ierr = unsafe { bind_ceed::CeedVectorAXPY(self.ptr, alpha, x.ptr) };
397*9df49d7eSJed Brown         self.ceed.check_error(ierr)?;
398*9df49d7eSJed Brown         Ok(self)
399*9df49d7eSJed Brown     }
400*9df49d7eSJed Brown 
401*9df49d7eSJed Brown     /// Compute the pointwise multiplication w = x .* y for CeedVectors
402*9df49d7eSJed Brown     ///
403*9df49d7eSJed Brown     /// # arguments
404*9df49d7eSJed Brown     ///
405*9df49d7eSJed Brown     /// * `x` - first vector for product
406*9df49d7eSJed Brown     /// * `y` - second vector for product
407*9df49d7eSJed Brown     ///
408*9df49d7eSJed Brown     /// ```
409*9df49d7eSJed Brown     /// # use libceed::prelude::*;
410*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
411*9df49d7eSJed Brown     /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.]).unwrap();
412*9df49d7eSJed Brown     /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.]).unwrap();
413*9df49d7eSJed Brown     /// let y = ceed.vector_from_slice(&[0., 1., 2., 3., 4.]).unwrap();
414*9df49d7eSJed Brown     ///
415*9df49d7eSJed Brown     /// w = w.pointwise_mult(&x, &y).unwrap();
416*9df49d7eSJed Brown     /// w.view().iter().enumerate().for_each(|(i, &v)| {
417*9df49d7eSJed Brown     ///     assert_eq!(v, (i as f64).powf(2.0), "Value not set correctly");
418*9df49d7eSJed Brown     /// });
419*9df49d7eSJed Brown     /// ```
420*9df49d7eSJed Brown     #[allow(unused_mut)]
421*9df49d7eSJed Brown     pub fn pointwise_mult(mut self, x: &crate::Vector, y: &crate::Vector) -> crate::Result<Self> {
422*9df49d7eSJed Brown         let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, x.ptr, y.ptr) };
423*9df49d7eSJed Brown         self.ceed.check_error(ierr)?;
424*9df49d7eSJed Brown         Ok(self)
425*9df49d7eSJed Brown     }
426*9df49d7eSJed Brown 
427*9df49d7eSJed Brown     /// Compute the pointwise multiplication w = w .* x for CeedVectors
428*9df49d7eSJed Brown     ///
429*9df49d7eSJed Brown     /// # arguments
430*9df49d7eSJed Brown     ///
431*9df49d7eSJed Brown     /// * `x` - second vector for product
432*9df49d7eSJed Brown     ///
433*9df49d7eSJed Brown     /// ```
434*9df49d7eSJed Brown     /// # use libceed::prelude::*;
435*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
436*9df49d7eSJed Brown     /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.]).unwrap();
437*9df49d7eSJed Brown     /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.]).unwrap();
438*9df49d7eSJed Brown     ///
439*9df49d7eSJed Brown     /// w = w.pointwise_scale(&x).unwrap();
440*9df49d7eSJed Brown     /// w.view().iter().enumerate().for_each(|(i, &v)| {
441*9df49d7eSJed Brown     ///     assert_eq!(v, (i as f64).powf(2.0), "Value not set correctly");
442*9df49d7eSJed Brown     /// });
443*9df49d7eSJed Brown     /// ```
444*9df49d7eSJed Brown     #[allow(unused_mut)]
445*9df49d7eSJed Brown     pub fn pointwise_scale(mut self, x: &crate::Vector) -> crate::Result<Self> {
446*9df49d7eSJed Brown         let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, self.ptr, x.ptr) };
447*9df49d7eSJed Brown         self.ceed.check_error(ierr)?;
448*9df49d7eSJed Brown         Ok(self)
449*9df49d7eSJed Brown     }
450*9df49d7eSJed Brown 
451*9df49d7eSJed Brown     /// Compute the pointwise multiplication w = w .* w for a CeedVector
452*9df49d7eSJed Brown     ///
453*9df49d7eSJed Brown     /// ```
454*9df49d7eSJed Brown     /// # use libceed::prelude::*;
455*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
456*9df49d7eSJed Brown     /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.]).unwrap();
457*9df49d7eSJed Brown     ///
458*9df49d7eSJed Brown     /// w = w.pointwise_square().unwrap();
459*9df49d7eSJed Brown     /// w.view().iter().enumerate().for_each(|(i, &v)| {
460*9df49d7eSJed Brown     ///     assert_eq!(v, (i as f64).powf(2.0), "Value not set correctly");
461*9df49d7eSJed Brown     /// });
462*9df49d7eSJed Brown     /// ```
463*9df49d7eSJed Brown     #[allow(unused_mut)]
464*9df49d7eSJed Brown     pub fn pointwise_square(mut self) -> crate::Result<Self> {
465*9df49d7eSJed Brown         let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, self.ptr, self.ptr) };
466*9df49d7eSJed Brown         self.ceed.check_error(ierr)?;
467*9df49d7eSJed Brown         Ok(self)
468*9df49d7eSJed Brown     }
469*9df49d7eSJed Brown }
470*9df49d7eSJed Brown 
471*9df49d7eSJed Brown // -----------------------------------------------------------------------------
472*9df49d7eSJed Brown // Vector Viewer
473*9df49d7eSJed Brown // -----------------------------------------------------------------------------
474*9df49d7eSJed Brown /// A (host) view of a Vector with Deref to slice.  We can't make
475*9df49d7eSJed Brown /// Vector itself Deref to slice because we can't handle the drop to
476*9df49d7eSJed Brown /// call bind_ceed::CeedVectorRestoreArrayRead().
477*9df49d7eSJed Brown #[derive(Debug)]
478*9df49d7eSJed Brown pub struct VectorView<'a> {
479*9df49d7eSJed Brown     vec: &'a Vector<'a>,
480*9df49d7eSJed Brown     array: *const f64,
481*9df49d7eSJed Brown }
482*9df49d7eSJed Brown 
483*9df49d7eSJed Brown impl<'a> VectorView<'a> {
484*9df49d7eSJed Brown     /// Construct a VectorView from a Vector reference
485*9df49d7eSJed Brown     fn new(vec: &'a Vector) -> Self {
486*9df49d7eSJed Brown         let mut array = std::ptr::null();
487*9df49d7eSJed Brown         unsafe {
488*9df49d7eSJed Brown             bind_ceed::CeedVectorGetArrayRead(
489*9df49d7eSJed Brown                 vec.ptr,
490*9df49d7eSJed Brown                 crate::MemType::Host as bind_ceed::CeedMemType,
491*9df49d7eSJed Brown                 &mut array,
492*9df49d7eSJed Brown             );
493*9df49d7eSJed Brown         }
494*9df49d7eSJed Brown         Self {
495*9df49d7eSJed Brown             vec: vec,
496*9df49d7eSJed Brown             array: array,
497*9df49d7eSJed Brown         }
498*9df49d7eSJed Brown     }
499*9df49d7eSJed Brown }
500*9df49d7eSJed Brown 
501*9df49d7eSJed Brown // Destructor
502*9df49d7eSJed Brown impl<'a> Drop for VectorView<'a> {
503*9df49d7eSJed Brown     fn drop(&mut self) {
504*9df49d7eSJed Brown         unsafe {
505*9df49d7eSJed Brown             bind_ceed::CeedVectorRestoreArrayRead(self.vec.ptr, &mut self.array);
506*9df49d7eSJed Brown         }
507*9df49d7eSJed Brown     }
508*9df49d7eSJed Brown }
509*9df49d7eSJed Brown 
510*9df49d7eSJed Brown // Data access
511*9df49d7eSJed Brown impl<'a> Deref for VectorView<'a> {
512*9df49d7eSJed Brown     type Target = [f64];
513*9df49d7eSJed Brown     fn deref(&self) -> &[f64] {
514*9df49d7eSJed Brown         unsafe { std::slice::from_raw_parts(self.array, self.vec.len()) }
515*9df49d7eSJed Brown     }
516*9df49d7eSJed Brown }
517*9df49d7eSJed Brown 
518*9df49d7eSJed Brown // Viewing
519*9df49d7eSJed Brown impl<'a> fmt::Display for VectorView<'a> {
520*9df49d7eSJed Brown     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
521*9df49d7eSJed Brown         write!(f, "VectorView({:?})", self.deref())
522*9df49d7eSJed Brown     }
523*9df49d7eSJed Brown }
524*9df49d7eSJed Brown 
525*9df49d7eSJed Brown // -----------------------------------------------------------------------------
526*9df49d7eSJed Brown // Vector Viewer Mutable
527*9df49d7eSJed Brown // -----------------------------------------------------------------------------
528*9df49d7eSJed Brown /// A mutable (host) view of a Vector with Deref to slice.
529*9df49d7eSJed Brown #[derive(Debug)]
530*9df49d7eSJed Brown pub struct VectorViewMut<'a> {
531*9df49d7eSJed Brown     vec: &'a Vector<'a>,
532*9df49d7eSJed Brown     array: *mut f64,
533*9df49d7eSJed Brown }
534*9df49d7eSJed Brown 
535*9df49d7eSJed Brown impl<'a> VectorViewMut<'a> {
536*9df49d7eSJed Brown     /// Construct a VectorViewMut from a Vector reference
537*9df49d7eSJed Brown     fn new(vec: &'a mut Vector) -> Self {
538*9df49d7eSJed Brown         let mut ptr = std::ptr::null_mut();
539*9df49d7eSJed Brown         unsafe {
540*9df49d7eSJed Brown             bind_ceed::CeedVectorGetArray(
541*9df49d7eSJed Brown                 vec.ptr,
542*9df49d7eSJed Brown                 crate::MemType::Host as bind_ceed::CeedMemType,
543*9df49d7eSJed Brown                 &mut ptr,
544*9df49d7eSJed Brown             );
545*9df49d7eSJed Brown         }
546*9df49d7eSJed Brown         Self {
547*9df49d7eSJed Brown             vec: vec,
548*9df49d7eSJed Brown             array: ptr,
549*9df49d7eSJed Brown         }
550*9df49d7eSJed Brown     }
551*9df49d7eSJed Brown }
552*9df49d7eSJed Brown 
553*9df49d7eSJed Brown // Destructor
554*9df49d7eSJed Brown impl<'a> Drop for VectorViewMut<'a> {
555*9df49d7eSJed Brown     fn drop(&mut self) {
556*9df49d7eSJed Brown         unsafe {
557*9df49d7eSJed Brown             bind_ceed::CeedVectorRestoreArray(self.vec.ptr, &mut self.array);
558*9df49d7eSJed Brown         }
559*9df49d7eSJed Brown     }
560*9df49d7eSJed Brown }
561*9df49d7eSJed Brown 
562*9df49d7eSJed Brown // Data access
563*9df49d7eSJed Brown impl<'a> Deref for VectorViewMut<'a> {
564*9df49d7eSJed Brown     type Target = [f64];
565*9df49d7eSJed Brown     fn deref(&self) -> &[f64] {
566*9df49d7eSJed Brown         unsafe { std::slice::from_raw_parts(self.array, self.vec.len()) }
567*9df49d7eSJed Brown     }
568*9df49d7eSJed Brown }
569*9df49d7eSJed Brown 
570*9df49d7eSJed Brown // Mutable data access
571*9df49d7eSJed Brown impl<'a> DerefMut for VectorViewMut<'a> {
572*9df49d7eSJed Brown     fn deref_mut(&mut self) -> &mut [f64] {
573*9df49d7eSJed Brown         unsafe { std::slice::from_raw_parts_mut(self.array, self.vec.len()) }
574*9df49d7eSJed Brown     }
575*9df49d7eSJed Brown }
576*9df49d7eSJed Brown 
577*9df49d7eSJed Brown // Viewing
578*9df49d7eSJed Brown impl<'a> fmt::Display for VectorViewMut<'a> {
579*9df49d7eSJed Brown     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
580*9df49d7eSJed Brown         write!(f, "VectorViewMut({:?})", self.deref())
581*9df49d7eSJed Brown     }
582*9df49d7eSJed Brown }
583*9df49d7eSJed Brown 
584*9df49d7eSJed Brown // -----------------------------------------------------------------------------
585