Skip to main content

faer/row/
rowref.rs

1use super::*;
2use crate::utils::bound::{Array, Dim, Partition};
3use crate::{ContiguousFwd, Idx, IdxInc};
4use equator::{assert, debug_assert};
5use faer_traits::Real;
6/// see [`super::RowRef`]
7pub struct Ref<'a, T, Cols = usize, CStride = isize> {
8	pub(crate) trans: ColRef<'a, T, Cols, CStride>,
9}
10impl<T, Rows: Copy, CStride: Copy> Copy for Ref<'_, T, Rows, CStride> {}
11impl<T, Rows: Copy, CStride: Copy> Clone for Ref<'_, T, Rows, CStride> {
12	#[inline]
13	fn clone(&self) -> Self {
14		*self
15	}
16}
17impl<'short, T, Rows: Copy, CStride: Copy> Reborrow<'short>
18	for Ref<'_, T, Rows, CStride>
19{
20	type Target = Ref<'short, T, Rows, CStride>;
21
22	#[inline]
23	fn rb(&'short self) -> Self::Target {
24		*self
25	}
26}
27impl<'short, T, Rows: Copy, CStride: Copy> ReborrowMut<'short>
28	for Ref<'_, T, Rows, CStride>
29{
30	type Target = Ref<'short, T, Rows, CStride>;
31
32	#[inline]
33	fn rb_mut(&'short mut self) -> Self::Target {
34		*self
35	}
36}
37impl<'a, T, Rows: Copy, CStride: Copy> IntoConst for Ref<'a, T, Rows, CStride> {
38	type Target = Ref<'a, T, Rows, CStride>;
39
40	#[inline]
41	fn into_const(self) -> Self::Target {
42		self
43	}
44}
45unsafe impl<T: Sync, Rows: Sync, CStride: Sync> Sync
46	for Ref<'_, T, Rows, CStride>
47{
48}
49unsafe impl<T: Sync, Rows: Send, CStride: Send> Send
50	for Ref<'_, T, Rows, CStride>
51{
52}
53impl<'a, T> RowRef<'a, T> {
54	/// creates a row view over the given element
55	#[inline]
56	pub fn from_ref(value: &'a T) -> Self {
57		unsafe { RowRef::from_raw_parts(value as *const T, 1, 1) }
58	}
59
60	/// creates a `RowRef` from slice views over the row vector data, the result
61	/// has the same number of columns as the length of the input slice
62	#[inline]
63	pub fn from_slice(slice: &'a [T]) -> Self {
64		let len = slice.len();
65		unsafe { Self::from_raw_parts(slice.as_ptr(), len, 1) }
66	}
67}
68impl<'a, T, Cols: Shape, CStride: Stride> RowRef<'a, T, Cols, CStride> {
69	/// creates a `RowRef` from pointers to the column vector data, number of
70	/// rows, and row stride
71	///
72	/// # safety
73	/// this function has the same safety requirements as
74	/// [`MatRef::from_raw_parts(ptr, 1, ncols, 0, col_stride)`]
75	#[inline(always)]
76	#[track_caller]
77	pub const unsafe fn from_raw_parts(
78		ptr: *const T,
79		ncols: Cols,
80		col_stride: CStride,
81	) -> Self {
82		Self {
83			0: Ref {
84				trans: ColRef::from_raw_parts(ptr, ncols, col_stride),
85			},
86		}
87	}
88
89	/// returns a pointer to the row data
90	#[inline(always)]
91	pub fn as_ptr(&self) -> *const T {
92		self.trans.as_ptr()
93	}
94
95	/// returns the number of rows of the row (always 1)
96	#[inline(always)]
97	pub fn nrows(&self) -> usize {
98		1
99	}
100
101	/// returns the number of columns of the row
102	#[inline(always)]
103	pub fn ncols(&self) -> Cols {
104		self.trans.nrows()
105	}
106
107	/// returns the number of rows and columns of the row
108	#[inline(always)]
109	pub fn shape(&self) -> (usize, Cols) {
110		(self.nrows(), self.ncols())
111	}
112
113	/// returns the column stride of the row
114	#[inline(always)]
115	pub fn col_stride(&self) -> CStride {
116		self.trans.row_stride()
117	}
118
119	#[inline]
120	pub fn map<U>(&self, f: impl FnMut(&T) -> U) -> Row<U, Cols> {
121		let mut f = f;
122		zip!(self).map(|unzip!(x)| f(x))
123	}
124
125	#[inline]
126	pub fn for_each(&self, f: impl FnMut(&T)) {
127		let mut f = f;
128		zip!(self).for_each(|unzip!(x)| f(x))
129	}
130
131	/// returns a raw pointer to the element at the given index
132	#[inline(always)]
133	pub fn ptr_at(&self, col: IdxInc<Cols>) -> *const T {
134		self.trans.ptr_at(col)
135	}
136
137	/// returns a raw pointer to the element at the given index, assuming the
138	/// provided index is within the row bounds
139	///
140	/// # safety
141	/// the behavior is undefined if any of the following conditions are
142	/// violated:
143	/// * `col < self.ncols()`
144	#[inline(always)]
145	#[track_caller]
146	pub unsafe fn ptr_inbounds_at(&self, col: Idx<Cols>) -> *const T {
147		debug_assert!(all(col < self.ncols()));
148		self.trans.ptr_inbounds_at(col)
149	}
150
151	/// splits the row vertically at the given column into two parts and returns
152	/// an array of each subrow, in the following order:
153	/// * left
154	/// * right
155	///
156	/// # panics
157	/// the function panics if the following condition is violated:
158	/// * `col <= self.ncols()`
159	#[inline]
160	#[track_caller]
161	pub fn split_at_col(
162		self,
163		col: IdxInc<Cols>,
164	) -> (RowRef<'a, T, usize, CStride>, RowRef<'a, T, usize, CStride>) {
165		assert!(all(col <= self.ncols()));
166		let rs = self.col_stride();
167		let top = self.as_ptr();
168		let bot = self.ptr_at(col);
169		unsafe {
170			(
171				RowRef::from_raw_parts(top, col.unbound(), rs),
172				RowRef::from_raw_parts(
173					bot,
174					self.ncols().unbound() - col.unbound(),
175					rs,
176				),
177			)
178		}
179	}
180
181	/// returns a view over the transpose of `self`
182	#[inline(always)]
183	pub fn transpose(self) -> ColRef<'a, T, Cols, CStride> {
184		self.trans
185	}
186
187	/// returns a view over the conjugate of `self`
188	#[inline(always)]
189	pub fn conjugate(self) -> RowRef<'a, T::Conj, Cols, CStride>
190	where
191		T: Conjugate,
192	{
193		RowRef {
194			0: Ref {
195				trans: self.trans.conjugate(),
196			},
197		}
198	}
199
200	/// returns an unconjugated view over `self`
201	#[inline(always)]
202	pub fn canonical(self) -> RowRef<'a, T::Canonical, Cols, CStride>
203	where
204		T: Conjugate,
205	{
206		RowRef {
207			0: Ref {
208				trans: self.trans.canonical(),
209			},
210		}
211	}
212
213	/// returns a view over the conjugate transpose of `self`
214	#[inline(always)]
215	pub fn adjoint(self) -> ColRef<'a, T::Conj, Cols, CStride>
216	where
217		T: Conjugate,
218	{
219		self.conjugate().transpose()
220	}
221
222	#[inline(always)]
223	#[track_caller]
224	pub(crate) fn at(self, col: Idx<Cols>) -> &'a T {
225		assert!(all(col < self.ncols()));
226		unsafe { self.at_unchecked(col) }
227	}
228
229	#[inline(always)]
230	#[track_caller]
231	pub(crate) unsafe fn at_unchecked(self, col: Idx<Cols>) -> &'a T {
232		&*self.ptr_inbounds_at(col)
233	}
234
235	/// returns a reference to the element at the given index, or a subrow if
236	/// `col` is a range, with bound checks
237	///
238	/// # panics
239	/// the function panics if any of the following conditions are violated:
240	/// * `col` must be contained in `[0, self.ncols())`
241	#[track_caller]
242	#[inline(always)]
243	pub fn get<ColRange>(
244		self,
245		col: ColRange,
246	) -> <RowRef<'a, T, Cols, CStride> as RowIndex<ColRange>>::Target
247	where
248		RowRef<'a, T, Cols, CStride>: RowIndex<ColRange>,
249	{
250		<RowRef<'a, T, Cols, CStride> as RowIndex<ColRange>>::get(self, col)
251	}
252
253	/// returns a reference to the element at the given index, or a subrow if
254	/// `col` is a range, without bound checks
255	///
256	/// # panics
257	/// the behavior is undefined if any of the following conditions are
258	/// violated:
259	/// * `col` must be contained in `[0, self.ncols())`
260	#[track_caller]
261	#[inline(always)]
262	pub unsafe fn get_unchecked<ColRange>(
263		self,
264		col: ColRange,
265	) -> <RowRef<'a, T, Cols, CStride> as RowIndex<ColRange>>::Target
266	where
267		RowRef<'a, T, Cols, CStride>: RowIndex<ColRange>,
268	{
269		unsafe {
270			<RowRef<'a, T, Cols, CStride> as RowIndex<ColRange>>::get_unchecked(
271				self, col,
272			)
273		}
274	}
275
276	/// returns a view over the `self`, with the columns in reversed order
277	#[inline]
278	pub fn reverse_cols(self) -> RowRef<'a, T, Cols, CStride::Rev> {
279		RowRef {
280			0: Ref {
281				trans: self.trans.reverse_rows(),
282			},
283		}
284	}
285
286	/// returns a view over the subrow starting at column `col_start`, and with
287	/// number of columns `ncols`
288	///
289	/// # panics
290	/// the function panics if any of the following conditions are violated:
291	/// * `col_start <= self.ncols()`
292	/// * `ncols <= self.ncols() - col_start`
293	#[inline]
294	pub fn subcols<V: Shape>(
295		self,
296		col_start: IdxInc<Cols>,
297		ncols: V,
298	) -> RowRef<'a, T, V, CStride> {
299		assert!(all(col_start <= self.ncols()));
300		{
301			let ncols = ncols.unbound();
302			let full_ncols = self.ncols().unbound();
303			let col_start = col_start.unbound();
304			assert!(all(ncols <= full_ncols - col_start));
305		}
306		let cs = self.col_stride();
307		unsafe { RowRef::from_raw_parts(self.ptr_at(col_start), ncols, cs) }
308	}
309
310	/// returns the input row with the given column shape after checking that it
311	/// matches the current column shape
312	#[inline]
313	#[track_caller]
314	pub fn as_col_shape<V: Shape>(self, ncols: V) -> RowRef<'a, T, V, CStride> {
315		assert!(all(self.ncols().unbound() == ncols.unbound()));
316		unsafe {
317			RowRef::from_raw_parts(self.as_ptr(), ncols, self.col_stride())
318		}
319	}
320
321	/// returns the input row with dynamic column shape
322	#[inline]
323	pub fn as_dyn_cols(self) -> RowRef<'a, T, usize, CStride> {
324		unsafe {
325			RowRef::from_raw_parts(
326				self.as_ptr(),
327				self.ncols().unbound(),
328				self.col_stride(),
329			)
330		}
331	}
332
333	/// returns the input row with dynamic stride
334	#[inline]
335	pub fn as_dyn_stride(self) -> RowRef<'a, T, Cols, isize> {
336		unsafe {
337			RowRef::from_raw_parts(
338				self.as_ptr(),
339				self.ncols(),
340				self.col_stride().element_stride(),
341			)
342		}
343	}
344
345	/// returns an iterator over the elements of the row
346	#[inline]
347	pub fn iter(
348		self,
349	) -> impl 'a + ExactSizeIterator + DoubleEndedIterator<Item = &'a T>
350	where
351		Cols: 'a,
352	{
353		self.trans.iter()
354	}
355
356	/// returns a parallel iterator over the elements of the row
357	#[inline]
358	#[cfg(feature = "rayon")]
359	pub fn par_iter(
360		self,
361	) -> impl 'a + rayon::iter::IndexedParallelIterator<Item = &'a T>
362	where
363		T: Sync,
364		Cols: 'a,
365	{
366		self.trans.par_iter()
367	}
368
369	/// returns a parallel iterator that provides exactly `count` successive
370	/// chunks of the elements of this row
371	///
372	/// available in every build
373	#[inline]
374	#[track_caller]
375	#[cfg(feature = "rayon")]
376	pub fn par_partition(
377		self,
378		count: usize,
379	) -> impl 'a
380	+ rayon::iter::IndexedParallelIterator<
381		Item = RowRef<'a, T, usize, CStride>,
382	>
383	where
384		T: Sync,
385		Cols: 'a,
386	{
387		use rayon::prelude::*;
388		self.transpose().par_partition(count).map(ColRef::transpose)
389	}
390
391	/// returns a view over the row with a static column stride equal to `+1`,
392	/// or `None` otherwise
393	#[inline]
394	pub fn try_as_row_major(
395		self,
396	) -> Option<RowRef<'a, T, Cols, ContiguousFwd>> {
397		if self.col_stride().element_stride() == 1 {
398			Some(unsafe {
399				RowRef::from_raw_parts(
400					self.as_ptr(),
401					self.ncols(),
402					ContiguousFwd,
403				)
404			})
405		} else {
406			None
407		}
408	}
409
410	#[inline(always)]
411	#[doc(hidden)]
412	pub unsafe fn const_cast(self) -> RowMut<'a, T, Cols, CStride> {
413		RowMut {
414			0: Mut {
415				trans: self.trans.const_cast(),
416			},
417		}
418	}
419
420	/// returns a matrix view over `self`
421	#[inline]
422	pub fn as_mat(self) -> MatRef<'a, T, usize, Cols, isize, CStride> {
423		self.transpose().as_mat().transpose()
424	}
425
426	/// interprets the row as a diagonal matrix
427	#[inline]
428	pub fn as_diagonal(self) -> DiagRef<'a, T, Cols, CStride> {
429		DiagRef {
430			0: crate::diag::Ref { inner: self.trans },
431		}
432	}
433
434	#[inline]
435	pub(crate) fn __at(self, i: Idx<Cols>) -> &'a T {
436		self.at(i)
437	}
438}
439impl<
440	T,
441	Cols: Shape,
442	CStride: Stride,
443	Inner: for<'short> Reborrow<'short, Target = Ref<'short, T, Cols, CStride>>,
444> generic::Row<Inner>
445{
446	/// returns a view over `self`
447	#[inline]
448	pub fn as_ref(&self) -> RowRef<'_, T, Cols, CStride> {
449		self.rb()
450	}
451
452	/// returns the maximum norm of `self`
453	#[inline]
454	pub fn norm_max(&self) -> Real<T>
455	where
456		T: Conjugate,
457	{
458		self.rb().as_mat().norm_max()
459	}
460
461	/// returns the l2 norm of `self`
462	#[inline]
463	pub fn norm_l2(&self) -> Real<T>
464	where
465		T: Conjugate,
466	{
467		self.rb().as_mat().norm_l2()
468	}
469
470	/// returns the squared l2 norm of `self`
471	#[inline]
472	pub fn squared_norm_l2(&self) -> Real<T>
473	where
474		T: Conjugate,
475	{
476		self.rb().as_mat().squared_norm_l2()
477	}
478
479	/// returns the l1 norm of `self`
480	#[inline]
481	pub fn norm_l1(&self) -> Real<T>
482	where
483		T: Conjugate,
484	{
485		self.rb().as_mat().norm_l1()
486	}
487
488	/// returns the sum of the elements of `self`
489	#[inline]
490	pub fn sum(&self) -> T::Canonical
491	where
492		T: Conjugate,
493	{
494		self.rb().as_mat().sum()
495	}
496
497	/// see [`Mat::kron`]
498	#[inline]
499	pub fn kron(
500		&self,
501		rhs: impl AsMatRef<T: Conjugate<Canonical = T::Canonical>>,
502	) -> Mat<T::Canonical>
503	where
504		T: Conjugate,
505	{
506		fn imp<T: ComplexField>(
507			lhs: MatRef<impl Conjugate<Canonical = T>>,
508			rhs: MatRef<impl Conjugate<Canonical = T>>,
509		) -> Mat<T> {
510			let mut out = Mat::zeros(
511				lhs.nrows() * rhs.nrows(),
512				lhs.ncols() * rhs.ncols(),
513			);
514			linalg::kron::kron(out.rb_mut(), lhs, rhs);
515			out
516		}
517		imp(
518			self.rb().as_mat().as_dyn().as_dyn_stride(),
519			rhs.as_mat_ref().as_dyn().as_dyn_stride(),
520		)
521	}
522
523	/// returns `true` if all of the elements of `self` are finite.
524	/// otherwise returns `false`.
525	#[inline]
526	pub fn is_all_finite(&self) -> bool
527	where
528		T: Conjugate,
529	{
530		self.rb().transpose().is_all_finite()
531	}
532
533	/// returns `true` if any of the elements of `self` is `NaN`.
534	/// otherwise returns `false`.
535	#[inline]
536	pub fn has_nan(&self) -> bool
537	where
538		T: Conjugate,
539	{
540		self.rb().transpose().has_nan()
541	}
542
543	/// returns a newly allocated row holding the cloned values of `self`
544	#[inline]
545	pub fn cloned(&self) -> Row<T, Cols>
546	where
547		T: Clone,
548	{
549		self.rb().transpose().cloned().into_transpose()
550	}
551
552	/// returns a newly allocated row holding the (possibly conjugated) values
553	/// of `self`
554	#[inline]
555	pub fn to_owned(&self) -> Row<T::Canonical, Cols>
556	where
557		T: Conjugate,
558	{
559		self.rb().transpose().to_owned().into_transpose()
560	}
561}
562impl<'a, T, Rows: Shape> RowRef<'a, T, Rows, ContiguousFwd> {
563	/// returns a reference over the elements as a slice
564	#[inline]
565	pub fn as_slice(self) -> &'a [T] {
566		self.transpose().as_slice()
567	}
568}
569impl<'a, 'ROWS, T> RowRef<'a, T, Dim<'ROWS>, ContiguousFwd> {
570	/// returns a reference over the elements as a lifetime-bound slice
571	#[inline]
572	pub fn as_array(self) -> &'a Array<'ROWS, T> {
573		self.transpose().as_array()
574	}
575}
576impl<'COLS, 'a, T, CStride: Stride> RowRef<'a, T, Dim<'COLS>, CStride> {
577	#[doc(hidden)]
578	#[inline]
579	pub fn split_cols_with<'LEFT, 'RIGHT>(
580		self,
581		col: Partition<'LEFT, 'RIGHT, 'COLS>,
582	) -> (
583		RowRef<'a, T, Dim<'LEFT>, CStride>,
584		RowRef<'a, T, Dim<'RIGHT>, CStride>,
585	) {
586		let (a, b) = self.split_at_col(col.midpoint());
587		(a.as_col_shape(col.head), b.as_col_shape(col.tail))
588	}
589}
590impl<T: core::fmt::Debug, Cols: Shape, CStride: Stride> core::fmt::Debug
591	for Ref<'_, T, Cols, CStride>
592{
593	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
594		fn imp<T: core::fmt::Debug>(
595			f: &mut core::fmt::Formatter<'_>,
596			this: RowRef<'_, T, Dim<'_>>,
597		) -> core::fmt::Result {
598			f.debug_list()
599				.entries(
600					this.ncols()
601						.indices()
602						.map(|j| crate::hacks::hijack_debug(this.at(j))),
603				)
604				.finish()
605		}
606		let this = generic::Row::from_inner_ref(self);
607		with_dim!(N, this.ncols().unbound());
608		imp(f, this.as_col_shape(N).as_dyn_stride())
609	}
610}
611impl<'a, T> RowRef<'a, T, usize, isize>
612where
613	T: RealField,
614{
615	/// Returns the maximum element in the row, or `None` if the row is empty
616	pub(crate) fn internal_max(self) -> Option<T> {
617		if self.nrows().unbound() == 0 || self.ncols() == 0 {
618			return None;
619		}
620		let mut max_val = self.get(0);
621		self.iter().for_each(|val| {
622			if val > max_val {
623				max_val = val;
624			}
625		});
626		Some((*max_val).clone())
627	}
628
629	/// Returns the minimum element in the row, or `None` if the row is empty
630	pub(crate) fn internal_min(self) -> Option<T> {
631		if self.nrows().unbound() == 0 || self.ncols() == 0 {
632			return None;
633		}
634		let mut min_val = self.get(0);
635		self.iter().for_each(|val| {
636			if val < min_val {
637				min_val = val;
638			}
639		});
640		Some((*min_val).clone())
641	}
642}
643impl<'a, T, Cols: Shape, CStride: Stride> RowRef<'a, T, Cols, CStride>
644where
645	T: RealField,
646{
647	/// Returns the maximum element in the row, or `None` if the row is empty
648	pub fn max(&self) -> Option<T> {
649		self.as_dyn_cols().as_dyn_stride().internal_max()
650	}
651
652	/// Returns the minimum element in the row, or `None` if the row is empty
653	pub fn min(&self) -> Option<T> {
654		self.as_dyn_cols().as_dyn_stride().internal_min()
655	}
656}
657#[cfg(test)]
658mod tests {
659	use crate::Row;
660	#[test]
661	fn test_row_min() {
662		let row: Row<f64> = Row::from_fn(5, |x| (x + 1) as f64);
663		let rowref = row.as_ref();
664		assert_eq!(rowref.min(), Some(1.0));
665		let empty: Row<f64> = Row::from_fn(0, |_| 0.0);
666		let emptyref = empty.as_ref();
667		assert_eq!(emptyref.min(), None);
668	}
669	#[test]
670	fn test_row_max() {
671		let row: Row<f64> = Row::from_fn(5, |x| (x + 1) as f64);
672		let rowref = row.as_ref();
673		assert_eq!(rowref.max(), Some(5.0));
674		let empty: Row<f64> = Row::from_fn(0, |_| 0.0);
675		let emptyref = empty.as_ref();
676		assert_eq!(emptyref.max(), None);
677	}
678}