xref: /libCEED/rust/libceed/src/vector.rs (revision ed094490f53e580908aa80e9fe815a6fd76d7526)
1 // Copyright (c) 2017-2025, Lawrence Livermore National Security, LLC and other CEED contributors.
2 // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3 //
4 // SPDX-License-Identifier: BSD-2-Clause
5 //
6 // This file is part of CEED:  http://github.com/ceed
7 
8 //! A Ceed Vector constitutes the main data structure and serves as input/output
9 //! for Ceed Operators.
10 
11 use std::{
12     ops::{Deref, DerefMut},
13     os::raw::c_char,
14 };
15 
16 use crate::prelude::*;
17 
18 // -----------------------------------------------------------------------------
19 // Vector option
20 // -----------------------------------------------------------------------------
21 #[derive(Debug)]
22 pub enum VectorOpt<'a> {
23     Some(&'a Vector<'a>),
24     Active,
25     None,
26 }
27 /// Construct a VectorOpt reference from a Vector reference
28 impl<'a> From<&'a Vector<'_>> for VectorOpt<'a> {
29     fn from(vec: &'a Vector) -> Self {
30         debug_assert!(vec.ptr != unsafe { bind_ceed::CEED_VECTOR_ACTIVE });
31         debug_assert!(vec.ptr != unsafe { bind_ceed::CEED_VECTOR_NONE });
32         Self::Some(vec)
33     }
34 }
35 impl<'a> VectorOpt<'a> {
36     /// Transform a Rust libCEED VectorOpt into C libCEED CeedVector
37     pub(crate) fn to_raw(&self) -> bind_ceed::CeedVector {
38         match self {
39             Self::Some(vec) => vec.ptr,
40             Self::Active => unsafe { bind_ceed::CEED_VECTOR_ACTIVE },
41             Self::None => unsafe { bind_ceed::CEED_VECTOR_NONE },
42         }
43     }
44 
45     /// Check if a VectorOpt is Some
46     ///
47     /// ```
48     /// # use libceed::{prelude::*, VectorOpt};
49     /// # fn main() -> libceed::Result<()> {
50     /// # let ceed = libceed::Ceed::default_init();
51     /// let vec = libceed::vector::Vector::from_slice(&ceed, &[1., 2., 3.])?;
52     /// let vec_opt = VectorOpt::from(&vec);
53     /// assert!(vec_opt.is_some(), "Incorrect VectorOpt");
54     ///
55     /// let vec_opt = VectorOpt::Active;
56     /// assert!(!vec_opt.is_some(), "Incorrect VectorOpt");
57     ///
58     /// let vec_opt = VectorOpt::None;
59     /// assert!(!vec_opt.is_some(), "Incorrect VectorOpt");
60     /// # Ok(())
61     /// # }
62     /// ```
63     pub fn is_some(&self) -> bool {
64         match self {
65             Self::Some(_) => true,
66             Self::Active => false,
67             Self::None => false,
68         }
69     }
70 
71     /// Check if a VectorOpt is Active
72     ///
73     /// ```
74     /// # use libceed::{prelude::*, VectorOpt};
75     /// # fn main() -> libceed::Result<()> {
76     /// # let ceed = libceed::Ceed::default_init();
77     /// let vec = libceed::vector::Vector::from_slice(&ceed, &[1., 2., 3.])?;
78     /// let vec_opt = VectorOpt::from(&vec);
79     /// assert!(!vec_opt.is_active(), "Incorrect VectorOpt");
80     ///
81     /// let vec_opt = VectorOpt::Active;
82     /// assert!(vec_opt.is_active(), "Incorrect VectorOpt");
83     ///
84     /// let vec_opt = VectorOpt::None;
85     /// assert!(!vec_opt.is_active(), "Incorrect VectorOpt");
86     /// # Ok(())
87     /// # }
88     /// ```
89     pub fn is_active(&self) -> bool {
90         match self {
91             Self::Some(_) => false,
92             Self::Active => true,
93             Self::None => false,
94         }
95     }
96 
97     /// Check if a VectorOpt is Some
98     ///
99     /// ```
100     /// # use libceed::{prelude::*, VectorOpt};
101     /// # fn main() -> libceed::Result<()> {
102     /// # let ceed = libceed::Ceed::default_init();
103     /// let vec = libceed::vector::Vector::from_slice(&ceed, &[1., 2., 3.])?;
104     /// let vec_opt = VectorOpt::from(&vec);
105     /// assert!(!vec_opt.is_none(), "Incorrect VectorOpt");
106     ///
107     /// let vec_opt = VectorOpt::Active;
108     /// assert!(!vec_opt.is_none(), "Incorrect VectorOpt");
109     ///
110     /// let vec_opt = VectorOpt::None;
111     /// assert!(vec_opt.is_none(), "Incorrect VectorOpt");
112     /// # Ok(())
113     /// # }
114     /// ```
115     pub fn is_none(&self) -> bool {
116         match self {
117             Self::Some(_) => false,
118             Self::Active => false,
119             Self::None => true,
120         }
121     }
122 }
123 
124 // -----------------------------------------------------------------------------
125 // Vector borrowed slice wrapper
126 // -----------------------------------------------------------------------------
127 pub struct VectorSliceWrapper<'a> {
128     pub(crate) vector: Vector<'a>,
129     pub(crate) _slice: &'a mut [crate::Scalar],
130 }
131 
132 // -----------------------------------------------------------------------------
133 // Destructor
134 // -----------------------------------------------------------------------------
135 impl<'a> Drop for VectorSliceWrapper<'a> {
136     fn drop(&mut self) {
137         unsafe {
138             bind_ceed::CeedVectorTakeArray(
139                 self.vector.ptr,
140                 crate::MemType::Host as bind_ceed::CeedMemType,
141                 std::ptr::null_mut(),
142             )
143         };
144     }
145 }
146 
147 // -----------------------------------------------------------------------------
148 // Convenience constructor
149 // -----------------------------------------------------------------------------
150 impl<'a> VectorSliceWrapper<'a> {
151     fn from_vector_and_slice_mut<'b>(
152         vec: &'b mut Vector,
153         slice: &'a mut [crate::Scalar],
154     ) -> crate::Result<Self> {
155         assert_eq!(vec.length(), slice.len());
156         let (host, copy_mode) = (
157             crate::MemType::Host as bind_ceed::CeedMemType,
158             crate::CopyMode::UsePointer as bind_ceed::CeedCopyMode,
159         );
160         vec.check_error(unsafe {
161             bind_ceed::CeedVectorSetArray(
162                 vec.ptr,
163                 host,
164                 copy_mode,
165                 slice.as_ptr() as *mut crate::Scalar,
166             )
167         })?;
168         Ok(Self {
169             vector: unsafe { Vector::from_raw(vec.ptr_copy_mut()?)? },
170             _slice: slice,
171         })
172     }
173 }
174 
175 // -----------------------------------------------------------------------------
176 // Vector context wrapper
177 // -----------------------------------------------------------------------------
178 #[derive(Debug)]
179 pub struct Vector<'a> {
180     pub(crate) ptr: bind_ceed::CeedVector,
181     _lifeline: PhantomData<&'a ()>,
182 }
183 impl From<&'_ Vector<'_>> for bind_ceed::CeedVector {
184     fn from(vec: &Vector) -> Self {
185         vec.ptr
186     }
187 }
188 
189 // -----------------------------------------------------------------------------
190 // Destructor
191 // -----------------------------------------------------------------------------
192 impl<'a> Drop for Vector<'a> {
193     fn drop(&mut self) {
194         let not_none_and_active = self.ptr != unsafe { bind_ceed::CEED_VECTOR_NONE }
195             && self.ptr != unsafe { bind_ceed::CEED_VECTOR_ACTIVE };
196 
197         if not_none_and_active {
198             unsafe { bind_ceed::CeedVectorDestroy(&mut self.ptr) };
199         }
200     }
201 }
202 
203 // -----------------------------------------------------------------------------
204 // Display
205 // -----------------------------------------------------------------------------
206 impl<'a> fmt::Display for Vector<'a> {
207     /// View a Vector
208     ///
209     /// ```
210     /// # use libceed::prelude::*;
211     /// # fn main() -> libceed::Result<()> {
212     /// # let ceed = libceed::Ceed::default_init();
213     /// let vec = libceed::vector::Vector::from_slice(&ceed, &[1., 2., 3.])?;
214     /// assert_eq!(
215     ///     vec.to_string(),
216     ///     "CeedVector length 3
217     ///     1.00000000
218     ///     2.00000000
219     ///     3.00000000
220     /// "
221     /// );
222     /// # Ok(())
223     /// # }
224     /// ```
225     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
226         let mut ptr = std::ptr::null_mut();
227         let mut sizeloc = crate::MAX_BUFFER_LENGTH;
228         let format = CString::new("%12.8f").expect("CString::new failed");
229         let format_c: *const c_char = format.into_raw();
230         let cstring = unsafe {
231             let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc);
232             bind_ceed::CeedVectorView(self.ptr, format_c, file);
233             bind_ceed::fclose(file);
234             CString::from_raw(ptr)
235         };
236         cstring.to_string_lossy().fmt(f)
237     }
238 }
239 
240 // -----------------------------------------------------------------------------
241 // Implementations
242 // -----------------------------------------------------------------------------
243 impl<'a> Vector<'a> {
244     // Constructors
245     pub fn create(ceed: &crate::Ceed, n: usize) -> crate::Result<Self> {
246         let n = isize::try_from(n).unwrap();
247         let mut ptr = std::ptr::null_mut();
248         ceed.check_error(unsafe { bind_ceed::CeedVectorCreate(ceed.ptr, n, &mut ptr) })?;
249         Ok(Self {
250             ptr,
251             _lifeline: PhantomData,
252         })
253     }
254 
255     pub(crate) unsafe fn from_raw(ptr: bind_ceed::CeedVector) -> crate::Result<Self> {
256         Ok(Self {
257             ptr,
258             _lifeline: PhantomData,
259         })
260     }
261 
262     fn ptr_copy_mut(&mut self) -> crate::Result<bind_ceed::CeedVector> {
263         let mut ptr_copy = std::ptr::null_mut();
264         self.check_error(unsafe { bind_ceed::CeedVectorReferenceCopy(self.ptr, &mut ptr_copy) })?;
265         Ok(ptr_copy)
266     }
267 
268     /// Copy the array of self into vec_copy
269     ///
270     /// # arguments
271     ///
272     /// * `vec_source` - vector to copy array values from
273     ///
274     /// ```
275     /// # use libceed::{prelude::*, Scalar};
276     /// # fn main() -> libceed::Result<()> {
277     /// # let ceed = libceed::Ceed::default_init();
278     /// let a = ceed.vector_from_slice(&[1., 2., 3.])?;
279     /// let mut b = ceed.vector(3)?;
280     ///
281     /// b.copy_from(&a)?;
282     /// for (i, v) in b.view()?.iter().enumerate() {
283     ///     assert_eq!(*v, (i + 1) as Scalar, "Copy contents not set correctly");
284     /// }
285     /// # Ok(())
286     /// # }
287     /// ```
288     /// ```
289     pub fn copy_from(&mut self, vec_source: &Vector) -> crate::Result<i32> {
290         self.check_error(unsafe { bind_ceed::CeedVectorCopy(vec_source.ptr, self.ptr) })
291     }
292 
293     /// Create a Vector from a slice
294     ///
295     /// # arguments
296     ///
297     /// * `slice` - values to initialize vector with
298     ///
299     /// ```
300     /// # use libceed::prelude::*;
301     /// # fn main() -> libceed::Result<()> {
302     /// # let ceed = libceed::Ceed::default_init();
303     /// let vec = libceed::Vector::from_slice(&ceed, &[1., 2., 3.])?;
304     /// assert_eq!(vec.length(), 3, "Incorrect length from slice");
305     /// # Ok(())
306     /// # }
307     /// ```
308     pub fn from_slice(ceed: &crate::Ceed, v: &[crate::Scalar]) -> crate::Result<Self> {
309         let mut x = Self::create(ceed, v.len())?;
310         x.set_slice(v)?;
311         Ok(x)
312     }
313 
314     /// Create a Vector from a mutable array reference
315     ///
316     /// # arguments
317     ///
318     /// * `slice` - values to initialize vector with
319     ///
320     /// ```
321     /// # use libceed::prelude::*;
322     /// # fn main() -> libceed::Result<()> {
323     /// # let ceed = libceed::Ceed::default_init();
324     /// let mut rust_vec = vec![1., 2., 3.];
325     /// let vec = libceed::vector::Vector::from_array(&ceed, &mut rust_vec)?;
326     ///
327     /// assert_eq!(vec.length(), 3, "Incorrect length from slice");
328     /// # Ok(())
329     /// # }
330     /// ```
331     pub fn from_array(ceed: &crate::Ceed, v: &mut [crate::Scalar]) -> crate::Result<Self> {
332         let x = Self::create(ceed, v.len())?;
333         let (host, user_pointer) = (
334             crate::MemType::Host as bind_ceed::CeedMemType,
335             crate::CopyMode::UsePointer as bind_ceed::CeedCopyMode,
336         );
337         let v = v.as_ptr() as *mut crate::Scalar;
338         ceed.check_error(unsafe { bind_ceed::CeedVectorSetArray(x.ptr, host, user_pointer, v) })?;
339         Ok(x)
340     }
341 
342     // Raw Ceed for error handling
343     #[doc(hidden)]
344     fn ceed(&self) -> bind_ceed::Ceed {
345         unsafe { bind_ceed::CeedVectorReturnCeed(self.ptr) }
346     }
347 
348     // Error handling
349     #[doc(hidden)]
350     fn check_error(&self, ierr: i32) -> crate::Result<i32> {
351         crate::check_error(|| self.ceed(), ierr)
352     }
353 
354     /// Returns the length of a Vector
355     ///
356     /// ```
357     /// # use libceed::prelude::*;
358     /// # fn main() -> libceed::Result<()> {
359     /// # let ceed = libceed::Ceed::default_init();
360     /// let vec = ceed.vector(10)?;
361     ///
362     /// let n = vec.length();
363     /// assert_eq!(n, 10, "Incorrect length");
364     /// # Ok(())
365     /// # }
366     /// ```
367     pub fn length(&self) -> usize {
368         let mut n = 0;
369         unsafe { bind_ceed::CeedVectorGetLength(self.ptr, &mut n) };
370         usize::try_from(n).unwrap()
371     }
372 
373     /// Returns the length of a Vector
374     ///
375     /// ```
376     /// # use libceed::prelude::*;
377     /// # fn main() -> libceed::Result<()> {
378     /// # let ceed = libceed::Ceed::default_init();
379     /// let vec = ceed.vector(10)?;
380     /// assert_eq!(vec.len(), 10, "Incorrect length");
381     /// # Ok(())
382     /// # }
383     /// ```
384     pub fn len(&self) -> usize {
385         self.length()
386     }
387 
388     /// Returns true if the Vector contains no elements
389     ///
390     /// ```
391     /// # use libceed::prelude::*;
392     /// # fn main() -> libceed::Result<()> {
393     /// # let ceed = libceed::Ceed::default_init();
394     /// let vec = ceed.vector(10)?;
395     /// assert!(!vec.is_empty(), "Incorrect emptiness");
396     /// let empty_vec = ceed.vector(0)?;
397     /// assert!(empty_vec.is_empty(), "Incorrect emptiness");
398     /// # Ok(())
399     /// # }
400     /// ```
401     pub fn is_empty(&self) -> bool {
402         self.length() == 0
403     }
404 
405     /// Set the Vector to a constant value
406     ///
407     /// # arguments
408     ///
409     /// * `val` - Value to be used
410     ///
411     /// ```
412     /// # use libceed::prelude::*;
413     /// # fn main() -> libceed::Result<()> {
414     /// # let ceed = libceed::Ceed::default_init();
415     /// let len = 10;
416     /// let mut vec = ceed.vector(len)?;
417     ///
418     /// let val = 42.0;
419     /// vec.set_value(val)?;
420     ///
421     /// for v in vec.view()?.iter() {
422     ///     assert_eq!(*v, val, "Value not set correctly");
423     /// }
424     /// # Ok(())
425     /// # }
426     /// ```
427     pub fn set_value(&mut self, value: crate::Scalar) -> crate::Result<i32> {
428         self.check_error(unsafe { bind_ceed::CeedVectorSetValue(self.ptr, value) })
429     }
430 
431     /// Set values from a slice of the same length
432     ///
433     /// # arguments
434     ///
435     /// * `slice` - values to into self; length must match
436     ///
437     /// ```
438     /// # use libceed::{prelude::*, Scalar};
439     /// # fn main() -> libceed::Result<()> {
440     /// # let ceed = libceed::Ceed::default_init();
441     /// let mut vec = ceed.vector(4)?;
442     /// vec.set_slice(&[10., 11., 12., 13.])?;
443     ///
444     /// for (i, v) in vec.view()?.iter().enumerate() {
445     ///     assert_eq!(*v, 10. + i as Scalar, "Slice not set correctly");
446     /// }
447     /// # Ok(())
448     /// # }
449     /// ```
450     pub fn set_slice(&mut self, slice: &[crate::Scalar]) -> crate::Result<i32> {
451         assert_eq!(self.length(), slice.len());
452         let (host, copy_mode) = (
453             crate::MemType::Host as bind_ceed::CeedMemType,
454             crate::CopyMode::CopyValues as bind_ceed::CeedCopyMode,
455         );
456         self.check_error(unsafe {
457             bind_ceed::CeedVectorSetArray(
458                 self.ptr,
459                 host,
460                 copy_mode,
461                 slice.as_ptr() as *mut crate::Scalar,
462             )
463         })
464     }
465 
466     /// Wrap a mutable slice in a Vector of the same length
467     ///
468     /// # arguments
469     ///
470     /// * `slice` - values to wrap in self; length must match
471     ///
472     /// ```
473     /// # use libceed::{prelude::*, Scalar};
474     /// # fn main() -> libceed::Result<()> {
475     /// # let ceed = libceed::Ceed::default_init();
476     /// let mut vec = ceed.vector(4)?;
477     /// let mut array = [10., 11., 12., 13.];
478     ///
479     /// {
480     ///     // `wrapper` holds a mutable reference to the wrapped slice
481     ///     //   that is dropped when `wrapper` goes out of scope
482     ///     let wrapper = vec.wrap_slice_mut(&mut array)?;
483     ///     for (i, v) in vec.view()?.iter().enumerate() {
484     ///         assert_eq!(*v, 10. + i as Scalar, "Slice not set correctly");
485     ///     }
486     ///
487     ///     // This line will not compile, as the `wrapper` holds mutable
488     ///     //   access to the `array`
489     ///     // array[0] = 5.0;
490     ///
491     ///     // Changes here are reflected in the `array`
492     ///     vec.set_value(5.0)?;
493     ///     for v in vec.view()?.iter() {
494     ///         assert_eq!(*v, 5.0 as Scalar, "Value not set correctly");
495     ///     }
496     /// }
497     ///
498     /// // 'array' remains changed
499     /// for v in array.iter() {
500     ///     assert_eq!(*v, 5.0 as Scalar, "Array not mutated correctly");
501     /// }
502     ///
503     /// // While changes to `vec` no longer affect `array`
504     /// vec.set_value(6.0)?;
505     /// for v in array.iter() {
506     ///     assert_eq!(*v, 5.0 as Scalar, "Array mutated without permission");
507     /// }
508     /// # Ok(())
509     /// # }
510     /// ```
511     pub fn wrap_slice_mut<'b>(
512         &mut self,
513         slice: &'b mut [crate::Scalar],
514     ) -> crate::Result<VectorSliceWrapper<'b>> {
515         VectorSliceWrapper::from_vector_and_slice_mut(self, slice)
516     }
517 
518     /// Sync the Vector to a specified memtype
519     ///
520     /// # arguments
521     ///
522     /// * `mtype` - Memtype to be synced
523     ///
524     /// ```
525     /// # use libceed::{prelude::*, MemType};
526     /// # fn main() -> libceed::Result<()> {
527     /// # let ceed = libceed::Ceed::default_init();
528     /// let len = 10;
529     /// let mut vec = ceed.vector(len)?;
530     ///
531     /// let val = 42.0;
532     /// vec.set_value(val);
533     /// vec.sync(MemType::Host)?;
534     ///
535     /// for v in vec.view()?.iter() {
536     ///     assert_eq!(*v, val, "Value not set correctly");
537     /// }
538     /// # Ok(())
539     /// # }
540     /// ```
541     pub fn sync(&self, mtype: crate::MemType) -> crate::Result<i32> {
542         self.check_error(unsafe {
543             bind_ceed::CeedVectorSyncArray(self.ptr, mtype as bind_ceed::CeedMemType)
544         })
545     }
546 
547     /// Create an immutable view
548     ///
549     /// ```
550     /// # use libceed::prelude::*;
551     /// # fn main() -> libceed::Result<()> {
552     /// # let ceed = libceed::Ceed::default_init();
553     /// let vec = ceed.vector_from_slice(&[10., 11., 12., 13.])?;
554     ///
555     /// let v = vec.view()?;
556     /// assert_eq!(v[0..2], [10., 11.]);
557     ///
558     /// // It is valid to have multiple immutable views
559     /// let w = vec.view()?;
560     /// assert_eq!(v[1..], w[1..]);
561     /// # Ok(())
562     /// # }
563     /// ```
564     pub fn view(&self) -> crate::Result<VectorView> {
565         VectorView::new(self)
566     }
567 
568     /// Create an mutable view
569     ///
570     /// ```
571     /// # use libceed::prelude::*;
572     /// # fn main() -> libceed::Result<()> {
573     /// # let ceed = libceed::Ceed::default_init();
574     /// let mut vec = ceed.vector_from_slice(&[10., 11., 12., 13.])?;
575     ///
576     /// {
577     ///     let mut v = vec.view_mut()?;
578     ///     v[2] = 9.;
579     /// }
580     ///
581     /// let w = vec.view()?;
582     /// assert_eq!(w[2], 9., "View did not mutate data");
583     /// # Ok(())
584     /// # }
585     /// ```
586     pub fn view_mut(&mut self) -> crate::Result<VectorViewMut> {
587         VectorViewMut::new(self)
588     }
589 
590     /// Return the norm of a Vector
591     ///
592     /// # arguments
593     ///
594     /// * `ntype` - Norm type One, Two, or Max
595     ///
596     /// ```
597     /// # use libceed::{prelude::*, NormType};
598     /// # fn main() -> libceed::Result<()> {
599     /// # let ceed = libceed::Ceed::default_init();
600     /// let vec = ceed.vector_from_slice(&[1., 2., 3., 4.])?;
601     ///
602     /// let max_norm = vec.norm(NormType::Max)?;
603     /// assert_eq!(max_norm, 4.0, "Incorrect Max norm");
604     ///
605     /// let l1_norm = vec.norm(NormType::One)?;
606     /// assert_eq!(l1_norm, 10., "Incorrect L1 norm");
607     ///
608     /// let l2_norm = vec.norm(NormType::Two)?;
609     /// assert!((l2_norm - 5.477) < 1e-3, "Incorrect L2 norm");
610     /// # Ok(())
611     /// # }
612     /// ```
613     pub fn norm(&self, ntype: crate::NormType) -> crate::Result<crate::Scalar> {
614         let mut res: crate::Scalar = 0.0;
615         self.check_error(unsafe {
616             bind_ceed::CeedVectorNorm(self.ptr, ntype as bind_ceed::CeedNormType, &mut res)
617         })?;
618         Ok(res)
619     }
620 
621     /// Compute x = alpha x for a Vector
622     ///
623     /// # arguments
624     ///
625     /// * `alpha` - scaling factor
626     ///
627     /// ```
628     /// # use libceed::{prelude::*, Scalar};
629     /// # fn main() -> libceed::Result<()> {
630     /// # let ceed = libceed::Ceed::default_init();
631     /// let mut vec = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
632     ///
633     /// vec = vec.scale(-1.0)?;
634     /// for (i, v) in vec.view()?.iter().enumerate() {
635     ///     assert_eq!(*v, -(i as Scalar), "Value not set correctly");
636     /// }
637     /// # Ok(())
638     /// # }
639     /// ```
640     #[allow(unused_mut)]
641     pub fn scale(mut self, alpha: crate::Scalar) -> crate::Result<Self> {
642         self.check_error(unsafe { bind_ceed::CeedVectorScale(self.ptr, alpha) })?;
643         Ok(self)
644     }
645 
646     /// Compute y = alpha x + y for a pair of Vectors
647     ///
648     /// # arguments
649     ///
650     /// * `alpha` - scaling factor
651     /// * `x`     - second vector, must be different than self
652     ///
653     /// ```
654     /// # use libceed::{prelude::*, Scalar};
655     /// # fn main() -> libceed::Result<()> {
656     /// # let ceed = libceed::Ceed::default_init();
657     /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
658     /// let mut y = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
659     ///
660     /// y = y.axpy(-0.5, &x)?;
661     /// for (i, y) in y.view()?.iter().enumerate() {
662     ///     assert_eq!(*y, (i as Scalar) / 2.0, "Value not set correctly");
663     /// }
664     /// # Ok(())
665     /// # }
666     /// ```
667     #[allow(unused_mut)]
668     pub fn axpy(mut self, alpha: crate::Scalar, x: &Vector) -> crate::Result<Self> {
669         self.check_error(unsafe { bind_ceed::CeedVectorAXPY(self.ptr, alpha, x.ptr) })?;
670         Ok(self)
671     }
672 
673     /// Compute y = alpha x + beta y for a pair of Vectors
674     ///
675     /// # arguments
676     ///
677     /// * `alpha` - first scaling factor
678     /// * `beta`  - second scaling factor
679     /// * `x`     - second vector, must be different than self
680     ///
681     /// ```
682     /// # use libceed::{prelude::*, Scalar};
683     /// # fn main() -> libceed::Result<()> {
684     /// # let ceed = libceed::Ceed::default_init();
685     /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
686     /// let mut y = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
687     ///
688     /// y = y.axpby(-0.5, 1.0, &x)?;
689     /// for (i, y) in y.view()?.iter().enumerate() {
690     ///     assert_eq!(*y, (i as Scalar) * 0.5, "Value not set correctly");
691     /// }
692     /// # Ok(())
693     /// # }
694     /// ```
695     #[allow(unused_mut)]
696     pub fn axpby(
697         mut self,
698         alpha: crate::Scalar,
699         beta: crate::Scalar,
700         x: &Vector,
701     ) -> crate::Result<Self> {
702         self.check_error(unsafe { bind_ceed::CeedVectorAXPBY(self.ptr, alpha, beta, x.ptr) })?;
703         Ok(self)
704     }
705 
706     /// Compute the pointwise multiplication w = x .* y for Vectors
707     ///
708     /// # arguments
709     ///
710     /// * `x` - first vector for product
711     /// * `y` - second vector for product
712     ///
713     /// ```
714     /// # use libceed::{prelude::*, Scalar};
715     /// # fn main() -> libceed::Result<()> {
716     /// # let ceed = libceed::Ceed::default_init();
717     /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
718     /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
719     /// let y = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
720     ///
721     /// w = w.pointwise_mult(&x, &y)?;
722     /// for (i, w) in w.view()?.iter().enumerate() {
723     ///     assert_eq!(*w, (i as Scalar).powf(2.0), "Value not set correctly");
724     /// }
725     /// # Ok(())
726     /// # }
727     /// ```
728     #[allow(unused_mut)]
729     pub fn pointwise_mult(mut self, x: &Vector, y: &Vector) -> crate::Result<Self> {
730         self.check_error(unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, x.ptr, y.ptr) })?;
731         Ok(self)
732     }
733 
734     /// Compute the pointwise multiplication w = w .* x for Vectors
735     ///
736     /// # arguments
737     ///
738     /// * `x` - second vector for product
739     ///
740     /// ```
741     /// # use libceed::{prelude::*, Scalar};
742     /// # fn main() -> libceed::Result<()> {
743     /// # let ceed = libceed::Ceed::default_init();
744     /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
745     /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
746     ///
747     /// w = w.pointwise_scale(&x)?;
748     /// for (i, w) in w.view()?.iter().enumerate() {
749     ///     assert_eq!(*w, (i as Scalar).powf(2.0), "Value not set correctly");
750     /// }
751     /// # Ok(())
752     /// # }
753     /// ```
754     #[allow(unused_mut)]
755     pub fn pointwise_scale(mut self, x: &Vector) -> crate::Result<Self> {
756         self.check_error(unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, self.ptr, x.ptr) })?;
757         Ok(self)
758     }
759 
760     /// Compute the pointwise multiplication w = w .* w for a Vector
761     ///
762     /// ```
763     /// # use libceed::{prelude::*, Scalar};
764     /// # fn main() -> libceed::Result<()> {
765     /// # let ceed = libceed::Ceed::default_init();
766     /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
767     ///
768     /// w = w.pointwise_square()?;
769     /// for (i, w) in w.view()?.iter().enumerate() {
770     ///     assert_eq!(*w, (i as Scalar).powf(2.0), "Value not set correctly");
771     /// }
772     /// # Ok(())
773     /// # }
774     /// ```
775     #[allow(unused_mut)]
776     pub fn pointwise_square(mut self) -> crate::Result<Self> {
777         self.check_error(unsafe {
778             bind_ceed::CeedVectorPointwiseMult(self.ptr, self.ptr, self.ptr)
779         })?;
780         Ok(self)
781     }
782 }
783 
784 // -----------------------------------------------------------------------------
785 // Vector Viewer
786 // -----------------------------------------------------------------------------
787 /// A (host) view of a Vector with Deref to slice.  We can't make
788 /// Vector itself Deref to slice because we can't handle the drop to
789 /// call bind_ceed::CeedVectorRestoreArrayRead().
790 #[derive(Debug)]
791 pub struct VectorView<'a> {
792     vec: &'a Vector<'a>,
793     array: *const crate::Scalar,
794 }
795 
796 impl<'a> VectorView<'a> {
797     /// Construct a VectorView from a Vector reference
798     fn new(vec: &'a Vector) -> crate::Result<Self> {
799         let mut array = std::ptr::null();
800         vec.check_error(unsafe {
801             bind_ceed::CeedVectorGetArrayRead(
802                 vec.ptr,
803                 crate::MemType::Host as bind_ceed::CeedMemType,
804                 &mut array,
805             )
806         })?;
807         Ok(Self { vec, array })
808     }
809 }
810 
811 // Destructor
812 impl<'a> Drop for VectorView<'a> {
813     fn drop(&mut self) {
814         unsafe {
815             bind_ceed::CeedVectorRestoreArrayRead(self.vec.ptr, &mut self.array);
816         }
817     }
818 }
819 
820 // Data access
821 impl<'a> Deref for VectorView<'a> {
822     type Target = [crate::Scalar];
823     fn deref(&self) -> &[crate::Scalar] {
824         unsafe { std::slice::from_raw_parts(self.array, self.vec.len()) }
825     }
826 }
827 
828 // Viewing
829 impl<'a> fmt::Display for VectorView<'a> {
830     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
831         write!(f, "VectorView({:?})", self.deref())
832     }
833 }
834 
835 // -----------------------------------------------------------------------------
836 // Vector Viewer Mutable
837 // -----------------------------------------------------------------------------
838 /// A mutable (host) view of a Vector with Deref to slice.
839 #[derive(Debug)]
840 pub struct VectorViewMut<'a> {
841     vec: &'a Vector<'a>,
842     array: *mut crate::Scalar,
843 }
844 
845 impl<'a> VectorViewMut<'a> {
846     /// Construct a VectorViewMut from a Vector reference
847     fn new(vec: &'a mut Vector) -> crate::Result<Self> {
848         let mut array = std::ptr::null_mut();
849         vec.check_error(unsafe {
850             bind_ceed::CeedVectorGetArray(
851                 vec.ptr,
852                 crate::MemType::Host as bind_ceed::CeedMemType,
853                 &mut array,
854             )
855         })?;
856         Ok(Self { vec, array })
857     }
858 }
859 
860 // Destructor
861 impl<'a> Drop for VectorViewMut<'a> {
862     fn drop(&mut self) {
863         unsafe {
864             bind_ceed::CeedVectorRestoreArray(self.vec.ptr, &mut self.array);
865         }
866     }
867 }
868 
869 // Data access
870 impl<'a> Deref for VectorViewMut<'a> {
871     type Target = [crate::Scalar];
872     fn deref(&self) -> &[crate::Scalar] {
873         unsafe { std::slice::from_raw_parts(self.array, self.vec.len()) }
874     }
875 }
876 
877 // Mutable data access
878 impl<'a> DerefMut for VectorViewMut<'a> {
879     fn deref_mut(&mut self) -> &mut [crate::Scalar] {
880         unsafe { std::slice::from_raw_parts_mut(self.array, self.vec.len()) }
881     }
882 }
883 
884 // Viewing
885 impl<'a> fmt::Display for VectorViewMut<'a> {
886     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
887         write!(f, "VectorViewMut({:?})", self.deref())
888     }
889 }
890 
891 // -----------------------------------------------------------------------------
892