Skip to main content

faer/linalg/
mat_ops.rs

1//! operator overloads. An operator has no room for a parallelism argument, so every overload
2//! that can run in parallel (the dense and sparse products) runs sequentially with `Par::Seq`.
3//! Use the explicit functions, for example [`crate::linalg::matmul::matmul`] and
4//! [`crate::sparse::linalg::matmul::sparse_sparse_matmul`], to choose a `Par`.
5use crate::internal_prelude::*;
6use crate::{Scale, assert, col, diag, mat, perm, row};
7use core::ops::{
8	Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign,
9};
10extern crate alloc;
11macro_rules! impl_binop {
12    (
13        { $(impl <$($ty_param:ident $(: $bound:tt)?),* $(,)?> $trait:ident <$rhs:ty > for
14        $lhs:ty { type Output = $out:ty; fn $name:ident ($self:ident, $rhs_:ident : _
15        $(,)?) $block:block })* }
16    ) => {
17        $(impl <$($ty_param $(: $bound)?,)*> $trait <&$rhs > for &$lhs { type Output =
18        $out; #[track_caller] fn $name ($self, $rhs_ : &$rhs) -> Self::Output $block }
19        impl <$($ty_param $(: $bound)?,)*> $trait <$rhs > for $lhs { type Output = $out;
20        #[track_caller] fn $name ($self, $rhs_ : $rhs) -> Self::Output { $trait ::$name
21        (&$self, &$rhs_) } } impl <$($ty_param $(: $bound)?,)*> $trait <$rhs > for &$lhs
22        { type Output = $out; #[track_caller] fn $name ($self, $rhs_ : $rhs) ->
23        Self::Output { $trait ::$name ($self, &$rhs_) } } impl <$($ty_param $(:
24        $bound)?,)*> $trait <&$rhs > for $lhs { type Output = $out; #[track_caller] fn
25        $name ($self, $rhs_ : &$rhs) -> Self::Output { $trait ::$name (&$self, $rhs_) }
26        })*
27    };
28}
29macro_rules! impl_op {
30    (
31        { $(impl <$($ty_param:ident $(: $bound:tt)?),* $(,)?> $trait:ident for $lhs:ty {
32        type Output = $out:ty; fn $name:ident ($self:ident $(,)?) $block:block })* }
33    ) => {
34        $(impl <$($ty_param $(: $bound)?,)*> $trait for &$lhs { type Output = $out;
35        #[track_caller] fn $name ($self) -> Self::Output $block } impl <$($ty_param $(:
36        $bound)?,)*> $trait for $lhs { type Output = $out; #[track_caller] fn $name
37        ($self) -> Self::Output { $trait ::$name (&$self) } })*
38    };
39}
40macro_rules! impl_op_assign {
41    (
42        { $(impl <$($ty_param:ident $(: $bound:tt)?),* $(,)?> $trait:ident <$rhs:ty > for
43        $lhs:ty { fn $name:ident (& mut $self:ident, $rhs_:ident : _ $(,)?) $block:block
44        })* }
45    ) => {
46        $(impl <$($ty_param $(: $bound)?,)*> $trait <&$rhs > for $lhs { #[track_caller]
47        fn $name (& mut $self, $rhs_ : &$rhs) $block } impl <$($ty_param $(: $bound)?,)*>
48        $trait <$rhs > for $lhs { #[track_caller] fn $name (& mut $self, $rhs_ : $rhs) {
49        $trait ::$name ($self, &$rhs_) } })*
50    };
51}
52impl<
53	LT: PartialEq<RT>,
54	LRows: Shape,
55	LCols: Shape,
56	LRStride: Stride,
57	LCStride: Stride,
58	RT,
59	RRows: Shape,
60	RCols: Shape,
61	RRStride: Stride,
62	RCStride: Stride,
63	L: for<'a> Reborrow<
64			'a,
65			Target = mat::Ref<'a, LT, LRows, LCols, LRStride, LCStride>,
66		>,
67	R: for<'a> Reborrow<
68			'a,
69			Target = mat::Ref<'a, RT, RRows, RCols, RRStride, RCStride>,
70		>,
71> PartialEq<mat::generic::Mat<R>> for mat::generic::Mat<L>
72{
73	fn eq(&self, other: &mat::generic::Mat<R>) -> bool {
74		fn imp<LT: PartialEq<RT>, RT>(
75			l: MatRef<'_, LT>,
76			r: MatRef<'_, RT>,
77		) -> bool {
78			if l.nrows() != r.nrows() {
79				return false;
80			}
81			with_dim!(M, l.nrows());
82			with_dim!(N, l.ncols());
83			let l = l.as_shape(M, N);
84			let r = r.as_shape(M, N);
85			for j in N.indices() {
86				for i in M.indices() {
87					if l[(i, j)] != r[(i, j)] {
88						return false;
89					}
90				}
91			}
92			true
93		}
94		imp(
95			self.rb().as_dyn().as_dyn_stride(),
96			other.rb().as_dyn().as_dyn_stride(),
97		)
98	}
99}
100impl<
101	LT: PartialEq<RT>,
102	LRows: Shape,
103	LRStride: Stride,
104	RT,
105	RRows: Shape,
106	RRStride: Stride,
107	L: for<'a> Reborrow<'a, Target = col::Ref<'a, LT, LRows, LRStride>>,
108	R: for<'a> Reborrow<'a, Target = col::Ref<'a, RT, RRows, RRStride>>,
109> PartialEq<col::generic::Col<R>> for col::generic::Col<L>
110{
111	fn eq(&self, other: &col::generic::Col<R>) -> bool {
112		fn imp<LT: PartialEq<RT>, RT>(
113			l: ColRef<'_, LT>,
114			r: ColRef<'_, RT>,
115		) -> bool {
116			if l.nrows() != r.nrows() {
117				return false;
118			}
119			with_dim!(N, l.nrows());
120			let l = l.as_row_shape(N);
121			let r = r.as_row_shape(N);
122			for i in N.indices() {
123				if l[i] != r[i] {
124					return false;
125				}
126			}
127			true
128		}
129		imp(
130			self.rb().as_dyn_rows().as_dyn_stride(),
131			other.rb().as_dyn_rows().as_dyn_stride(),
132		)
133	}
134}
135impl<
136	LT: PartialEq<RT>,
137	LCols: Shape,
138	LCStride: Stride,
139	RT,
140	RCols: Shape,
141	RCStride: Stride,
142	L: for<'a> Reborrow<'a, Target = row::Ref<'a, LT, LCols, LCStride>>,
143	R: for<'a> Reborrow<'a, Target = row::Ref<'a, RT, RCols, RCStride>>,
144> PartialEq<row::generic::Row<R>> for row::generic::Row<L>
145{
146	fn eq(&self, other: &row::generic::Row<R>) -> bool {
147		self.rb().transpose() == other.rb().transpose()
148	}
149}
150impl<
151	LT: PartialEq<RT>,
152	LDim: Shape,
153	LStride: Stride,
154	RT,
155	RDim: Shape,
156	RStride: Stride,
157	L: for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, LDim, LStride>>,
158	R: for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, RDim, RStride>>,
159> PartialEq<diag::generic::Diag<R>> for diag::generic::Diag<L>
160{
161	fn eq(&self, other: &diag::generic::Diag<R>) -> bool {
162		self.rb().column_vector() == other.rb().column_vector()
163	}
164}
165impl<
166	LI: Index,
167	LN: Shape,
168	RI: Index,
169	RN: Shape,
170	L: for<'a> Reborrow<'a, Target = perm::Ref<'a, LI, LN>>,
171	R: for<'a> Reborrow<'a, Target = perm::Ref<'a, RI, RN>>,
172> PartialEq<perm::generic::Perm<R>> for perm::generic::Perm<L>
173where
174	LN::Idx<LI>: PartialEq<RN::Idx<RI>>,
175{
176	#[inline]
177	fn eq(&self, other: &perm::generic::Perm<R>) -> bool {
178		self.rb().arrays().0 == other.rb().arrays().0
179	}
180}
181impl_op_assign!({
182	impl<
183		T: ComplexField,
184		Rows: Shape,
185		Cols: Shape,
186		LRStride: Stride,
187		LCStride: Stride,
188		RT: (Conjugate<Canonical = T>),
189		RRStride: Stride,
190		RCStride: Stride,
191		L: (for<'a> ReborrowMut<
192				'a,
193				Target = mat::Mut<'a, T, Rows, Cols, LRStride, LCStride>,
194			>),
195		R: (for<'a> Reborrow<
196				'a,
197				Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
198			>),
199	> SubAssign<mat::generic::Mat<R>> for mat::generic::Mat<L>
200	{
201		fn sub_assign(&mut self, rhs: _) {
202			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
203				lhs: MatMut<'_, T>,
204				rhs: MatRef<'_, RT>,
205			) {
206				zip!(lhs, rhs).for_each(sub_assign_fn::<T, RT>())
207			}
208			let lhs = self.rb_mut();
209			imp(
210				lhs.as_dyn_mut().as_dyn_stride_mut(),
211				rhs.rb().as_dyn().as_dyn_stride(),
212			);
213		}
214	}
215	impl<
216		T: ComplexField,
217		Rows: Shape,
218		LRStride: Stride,
219		RT: (Conjugate<Canonical = T>),
220		RRStride: Stride,
221		L: (for<'a> ReborrowMut<'a, Target = col::Mut<'a, T, Rows, LRStride>>),
222		R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
223	> SubAssign<col::generic::Col<R>> for col::generic::Col<L>
224	{
225		fn sub_assign(&mut self, rhs: _) {
226			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
227				lhs: ColMut<'_, T>,
228				rhs: ColRef<'_, RT>,
229			) {
230				zip!(lhs, rhs).for_each(sub_assign_fn::<T, RT>())
231			}
232			let lhs = self.rb_mut();
233			imp(
234				lhs.as_dyn_rows_mut().as_dyn_stride_mut(),
235				rhs.rb().as_dyn_rows().as_dyn_stride(),
236			);
237		}
238	}
239	impl<
240		T: ComplexField,
241		Cols: Shape,
242		LCStride: Stride,
243		RT: (Conjugate<Canonical = T>),
244		RCStride: Stride,
245		L: (for<'a> ReborrowMut<'a, Target = row::Mut<'a, T, Cols, LCStride>>),
246		R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
247	> SubAssign<row::generic::Row<R>> for row::generic::Row<L>
248	{
249		fn sub_assign(&mut self, rhs: _) {
250			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
251				lhs: RowMut<'_, T>,
252				rhs: RowRef<'_, RT>,
253			) {
254				SubAssign::sub_assign(
255					&mut lhs.transpose_mut(),
256					&rhs.transpose(),
257				)
258			}
259			let lhs = self.rb_mut();
260			imp(
261				lhs.as_dyn_cols_mut().as_dyn_stride_mut(),
262				rhs.rb().as_dyn_cols().as_dyn_stride(),
263			);
264		}
265	}
266	impl<
267		T: ComplexField,
268		Dim: Shape,
269		LStride: Stride,
270		RT: (Conjugate<Canonical = T>),
271		RStride: Stride,
272		L: (for<'a> ReborrowMut<'a, Target = diag::Mut<'a, T, Dim, LStride>>),
273		R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
274	> SubAssign<diag::generic::Diag<R>> for diag::generic::Diag<L>
275	{
276		fn sub_assign(&mut self, rhs: _) {
277			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
278				lhs: ColMut<'_, T>,
279				rhs: ColRef<'_, RT>,
280			) {
281				SubAssign::sub_assign(&mut { lhs }, &rhs)
282			}
283			let lhs = self.rb_mut();
284			imp(
285				lhs.column_vector_mut()
286					.as_dyn_rows_mut()
287					.as_dyn_stride_mut(),
288				rhs.rb().column_vector().as_dyn_rows().as_dyn_stride(),
289			);
290		}
291	}
292});
293impl_op_assign!({
294	impl<
295		T: ComplexField,
296		Rows: Shape,
297		Cols: Shape,
298		LRStride: Stride,
299		LCStride: Stride,
300		RT: (Conjugate<Canonical = T>),
301		RRStride: Stride,
302		RCStride: Stride,
303		L: (for<'a> ReborrowMut<
304				'a,
305				Target = mat::Mut<'a, T, Rows, Cols, LRStride, LCStride>,
306			>),
307		R: (for<'a> Reborrow<
308				'a,
309				Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
310			>),
311	> AddAssign<mat::generic::Mat<R>> for mat::generic::Mat<L>
312	{
313		fn add_assign(&mut self, rhs: _) {
314			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
315				lhs: MatMut<'_, T>,
316				rhs: MatRef<'_, RT>,
317			) {
318				zip!(lhs, rhs).for_each(add_assign_fn::<T, RT>())
319			}
320			let lhs = self.rb_mut();
321			imp(
322				lhs.as_dyn_mut().as_dyn_stride_mut(),
323				rhs.rb().as_dyn().as_dyn_stride(),
324			);
325		}
326	}
327	impl<
328		T: ComplexField,
329		Rows: Shape,
330		LRStride: Stride,
331		RT: (Conjugate<Canonical = T>),
332		RRStride: Stride,
333		L: (for<'a> ReborrowMut<'a, Target = col::Mut<'a, T, Rows, LRStride>>),
334		R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
335	> AddAssign<col::generic::Col<R>> for col::generic::Col<L>
336	{
337		fn add_assign(&mut self, rhs: _) {
338			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
339				lhs: ColMut<'_, T>,
340				rhs: ColRef<'_, RT>,
341			) {
342				zip!(lhs, rhs).for_each(add_assign_fn::<T, RT>())
343			}
344			let lhs = self.rb_mut();
345			imp(
346				lhs.as_dyn_rows_mut().as_dyn_stride_mut(),
347				rhs.rb().as_dyn_rows().as_dyn_stride(),
348			);
349		}
350	}
351	impl<
352		T: ComplexField,
353		Cols: Shape,
354		LCStride: Stride,
355		RT: (Conjugate<Canonical = T>),
356		RCStride: Stride,
357		L: (for<'a> ReborrowMut<'a, Target = row::Mut<'a, T, Cols, LCStride>>),
358		R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
359	> AddAssign<row::generic::Row<R>> for row::generic::Row<L>
360	{
361		fn add_assign(&mut self, rhs: _) {
362			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
363				lhs: RowMut<'_, T>,
364				rhs: RowRef<'_, RT>,
365			) {
366				AddAssign::add_assign(
367					&mut lhs.transpose_mut(),
368					&rhs.transpose(),
369				)
370			}
371			let lhs = self.rb_mut();
372			imp(
373				lhs.as_dyn_cols_mut().as_dyn_stride_mut(),
374				rhs.rb().as_dyn_cols().as_dyn_stride(),
375			);
376		}
377	}
378	impl<
379		T: ComplexField,
380		Dim: Shape,
381		LStride: Stride,
382		RT: (Conjugate<Canonical = T>),
383		RStride: Stride,
384		L: (for<'a> ReborrowMut<'a, Target = diag::Mut<'a, T, Dim, LStride>>),
385		R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
386	> AddAssign<diag::generic::Diag<R>> for diag::generic::Diag<L>
387	{
388		fn add_assign(&mut self, rhs: _) {
389			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
390				lhs: ColMut<'_, T>,
391				rhs: ColRef<'_, RT>,
392			) {
393				AddAssign::add_assign(&mut { lhs }, &rhs)
394			}
395			let lhs = self.rb_mut();
396			imp(
397				lhs.column_vector_mut()
398					.as_dyn_rows_mut()
399					.as_dyn_stride_mut(),
400				rhs.rb().column_vector().as_dyn_rows().as_dyn_stride(),
401			);
402		}
403	}
404});
405impl_binop!({
406	impl<
407		T: ComplexField,
408		Rows: Shape,
409		Cols: Shape,
410		LT: (Conjugate<Canonical = T>),
411		LRStride: Stride,
412		LCStride: Stride,
413		RT: (Conjugate<Canonical = T>),
414		RRStride: Stride,
415		RCStride: Stride,
416		L: (for<'a> Reborrow<
417				'a,
418				Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
419			>),
420		R: (for<'a> Reborrow<
421				'a,
422				Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
423			>),
424	> Add<mat::generic::Mat<R>> for mat::generic::Mat<L>
425	{
426		type Output = Mat<T, Rows, Cols>;
427
428		fn add(self, rhs: _) {
429			#[track_caller]
430			fn imp<
431				T: ComplexField,
432				LT: Conjugate<Canonical = T>,
433				RT: Conjugate<Canonical = T>,
434			>(
435				lhs: MatRef<'_, LT>,
436				rhs: MatRef<'_, RT>,
437			) -> Mat<T> {
438				assert!(all(
439					lhs.nrows() == rhs.nrows(),
440					lhs.ncols() == rhs.ncols()
441				));
442				zip!(lhs, rhs).map(add_fn::<LT, RT>())
443			}
444			let lhs = self.rb();
445			imp(
446				lhs.as_dyn().as_dyn_stride(),
447				rhs.rb().as_dyn().as_dyn_stride(),
448			)
449			.into_shape(lhs.nrows(), lhs.ncols())
450		}
451	}
452	impl<
453		T: ComplexField,
454		Rows: Shape,
455		LT: (Conjugate<Canonical = T>),
456		LRStride: Stride,
457		RT: (Conjugate<Canonical = T>),
458		RRStride: Stride,
459		L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
460		R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
461	> Add<col::generic::Col<R>> for col::generic::Col<L>
462	{
463		type Output = Col<T, Rows>;
464
465		fn add(self, rhs: _) {
466			#[track_caller]
467			fn imp<
468				T: ComplexField,
469				LT: Conjugate<Canonical = T>,
470				RT: Conjugate<Canonical = T>,
471			>(
472				lhs: ColRef<'_, LT>,
473				rhs: ColRef<'_, RT>,
474			) -> Col<T> {
475				assert!(all(
476					lhs.nrows() == rhs.nrows(),
477					lhs.ncols() == rhs.ncols()
478				));
479				zip!(lhs, rhs).map(add_fn::<LT, RT>())
480			}
481			let lhs = self.rb();
482			imp(
483				lhs.as_dyn_rows().as_dyn_stride(),
484				rhs.rb().as_dyn_rows().as_dyn_stride(),
485			)
486			.into_row_shape(lhs.nrows())
487		}
488	}
489	impl<
490		T: ComplexField,
491		Cols: Shape,
492		LT: (Conjugate<Canonical = T>),
493		LCStride: Stride,
494		RT: (Conjugate<Canonical = T>),
495		RCStride: Stride,
496		L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
497		R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
498	> Add<row::generic::Row<R>> for row::generic::Row<L>
499	{
500		type Output = Row<T, Cols>;
501
502		fn add(self, rhs: _) {
503			#[track_caller]
504			fn imp<
505				T: ComplexField,
506				LT: Conjugate<Canonical = T>,
507				RT: Conjugate<Canonical = T>,
508			>(
509				lhs: RowRef<'_, LT>,
510				rhs: RowRef<'_, RT>,
511			) -> Row<T> {
512				assert!(all(
513					lhs.nrows() == rhs.nrows(),
514					lhs.ncols() == rhs.ncols()
515				));
516				(lhs.transpose() + rhs.transpose()).into_transpose()
517			}
518			let lhs = self.rb();
519			imp(
520				lhs.as_dyn_cols().as_dyn_stride(),
521				rhs.rb().as_dyn_cols().as_dyn_stride(),
522			)
523			.into_col_shape(lhs.ncols())
524		}
525	}
526	impl<
527		T: ComplexField,
528		Dim: Shape,
529		LT: (Conjugate<Canonical = T>),
530		LStride: Stride,
531		RT: (Conjugate<Canonical = T>),
532		RStride: Stride,
533		L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
534		R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
535	> Add<diag::generic::Diag<R>> for diag::generic::Diag<L>
536	{
537		type Output = Diag<T, Dim>;
538
539		fn add(self, rhs: _) {
540			#[track_caller]
541			fn imp<
542				T: ComplexField,
543				LT: Conjugate<Canonical = T>,
544				RT: Conjugate<Canonical = T>,
545			>(
546				lhs: ColRef<'_, LT>,
547				rhs: ColRef<'_, RT>,
548			) -> Col<T> {
549				assert!(all(lhs.nrows() == rhs.nrows()));
550				lhs + rhs
551			}
552			let lhs = self.rb();
553			imp(
554				lhs.column_vector().as_dyn_rows().as_dyn_stride(),
555				rhs.rb().column_vector().as_dyn_rows().as_dyn_stride(),
556			)
557			.into_row_shape(lhs.dim())
558			.into_diagonal()
559		}
560	}
561});
562impl_binop!({
563	impl<
564		T: ComplexField,
565		Rows: Shape,
566		Cols: Shape,
567		LT: (Conjugate<Canonical = T>),
568		LRStride: Stride,
569		LCStride: Stride,
570		RT: (Conjugate<Canonical = T>),
571		RRStride: Stride,
572		RCStride: Stride,
573		L: (for<'a> Reborrow<
574				'a,
575				Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
576			>),
577		R: (for<'a> Reborrow<
578				'a,
579				Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
580			>),
581	> Sub<mat::generic::Mat<R>> for mat::generic::Mat<L>
582	{
583		type Output = Mat<T, Rows, Cols>;
584
585		fn sub(self, rhs: _) {
586			#[track_caller]
587			fn imp<
588				T: ComplexField,
589				LT: Conjugate<Canonical = T>,
590				RT: Conjugate<Canonical = T>,
591			>(
592				lhs: MatRef<'_, LT>,
593				rhs: MatRef<'_, RT>,
594			) -> Mat<T> {
595				assert!(all(
596					lhs.nrows() == rhs.nrows(),
597					lhs.ncols() == rhs.ncols()
598				));
599				zip!(lhs, rhs).map(sub_fn::<LT, RT>())
600			}
601			let lhs = self.rb();
602			imp(
603				lhs.as_dyn().as_dyn_stride(),
604				rhs.rb().as_dyn().as_dyn_stride(),
605			)
606			.into_shape(lhs.nrows(), lhs.ncols())
607		}
608	}
609	impl<
610		T: ComplexField,
611		Rows: Shape,
612		LT: (Conjugate<Canonical = T>),
613		LRStride: Stride,
614		RT: (Conjugate<Canonical = T>),
615		RRStride: Stride,
616		L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
617		R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
618	> Sub<col::generic::Col<R>> for col::generic::Col<L>
619	{
620		type Output = Col<T, Rows>;
621
622		fn sub(self, rhs: _) {
623			#[track_caller]
624			fn imp<
625				T: ComplexField,
626				LT: Conjugate<Canonical = T>,
627				RT: Conjugate<Canonical = T>,
628			>(
629				lhs: ColRef<'_, LT>,
630				rhs: ColRef<'_, RT>,
631			) -> Col<T> {
632				assert!(all(
633					lhs.nrows() == rhs.nrows(),
634					lhs.ncols() == rhs.ncols()
635				));
636				zip!(lhs, rhs).map(sub_fn::<LT, RT>())
637			}
638			let lhs = self.rb();
639			imp(
640				lhs.as_dyn_rows().as_dyn_stride(),
641				rhs.rb().as_dyn_rows().as_dyn_stride(),
642			)
643			.into_row_shape(lhs.nrows())
644		}
645	}
646	impl<
647		T: ComplexField,
648		Cols: Shape,
649		LT: (Conjugate<Canonical = T>),
650		LCStride: Stride,
651		RT: (Conjugate<Canonical = T>),
652		RCStride: Stride,
653		L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
654		R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
655	> Sub<row::generic::Row<R>> for row::generic::Row<L>
656	{
657		type Output = Row<T, Cols>;
658
659		fn sub(self, rhs: _) {
660			#[track_caller]
661			fn imp<
662				T: ComplexField,
663				LT: Conjugate<Canonical = T>,
664				RT: Conjugate<Canonical = T>,
665			>(
666				lhs: RowRef<'_, LT>,
667				rhs: RowRef<'_, RT>,
668			) -> Row<T> {
669				assert!(all(
670					lhs.nrows() == rhs.nrows(),
671					lhs.ncols() == rhs.ncols()
672				));
673				(lhs.transpose() - rhs.transpose()).into_transpose()
674			}
675			let lhs = self.rb();
676			imp(
677				lhs.as_dyn_cols().as_dyn_stride(),
678				rhs.rb().as_dyn_cols().as_dyn_stride(),
679			)
680			.into_col_shape(lhs.ncols())
681		}
682	}
683	impl<
684		T: ComplexField,
685		Dim: Shape,
686		LT: (Conjugate<Canonical = T>),
687		LStride: Stride,
688		RT: (Conjugate<Canonical = T>),
689		RStride: Stride,
690		L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
691		R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
692	> Sub<diag::generic::Diag<R>> for diag::generic::Diag<L>
693	{
694		type Output = Diag<T, Dim>;
695
696		fn sub(self, rhs: _) {
697			#[track_caller]
698			fn imp<
699				T: ComplexField,
700				LT: Conjugate<Canonical = T>,
701				RT: Conjugate<Canonical = T>,
702			>(
703				lhs: ColRef<'_, LT>,
704				rhs: ColRef<'_, RT>,
705			) -> Col<T> {
706				assert!(all(lhs.nrows() == rhs.nrows()));
707				lhs - rhs
708			}
709			let lhs = self.rb();
710			imp(
711				lhs.column_vector().as_dyn_rows().as_dyn_stride(),
712				rhs.rb().column_vector().as_dyn_rows().as_dyn_stride(),
713			)
714			.into_row_shape(lhs.dim())
715			.into_diagonal()
716		}
717	}
718});
719impl_op!({
720	impl<
721		T: Conjugate,
722		Rows: Shape,
723		Cols: Shape,
724		RStride: Stride,
725		CStride: Stride,
726		Inner: (for<'a> Reborrow<
727				'a,
728				Target = mat::Ref<'a, T, Rows, Cols, RStride, CStride>,
729			>),
730	> Neg for mat::generic::Mat<Inner>
731	{
732		type Output = Mat<T::Canonical, Rows, Cols>;
733
734		fn neg(self) {
735			#[track_caller]
736			fn imp<T: Conjugate>(A: MatRef<'_, T>) -> Mat<T::Canonical> {
737				zip!(A).map(neg_fn::<T>())
738			}
739			let A = self.rb();
740			imp(A.as_dyn().as_dyn_stride()).into_shape(A.nrows(), A.ncols())
741		}
742	}
743	impl<
744		T: Conjugate,
745		Rows: Shape,
746		RStride: Stride,
747		Inner: (for<'a> Reborrow<'a, Target = col::Ref<'a, T, Rows, RStride>>),
748	> Neg for col::generic::Col<Inner>
749	{
750		type Output = Col<T::Canonical, Rows>;
751
752		fn neg(self) {
753			#[track_caller]
754			fn imp<T: Conjugate>(A: ColRef<'_, T>) -> Col<T::Canonical> {
755				zip!(A).map(neg_fn::<T>())
756			}
757			let A = self.rb();
758			imp(A.as_dyn_rows().as_dyn_stride()).into_row_shape(A.nrows())
759		}
760	}
761	impl<
762		T: Conjugate,
763		Cols: Shape,
764		CStride: Stride,
765		Inner: (for<'a> Reborrow<'a, Target = row::Ref<'a, T, Cols, CStride>>),
766	> Neg for row::generic::Row<Inner>
767	{
768		type Output = Row<T::Canonical, Cols>;
769
770		fn neg(self) {
771			#[track_caller]
772			fn imp<T: Conjugate>(A: RowRef<'_, T>) -> Row<T::Canonical> {
773				(-A.transpose()).into_transpose()
774			}
775			let A = self.rb();
776			imp(A.as_dyn_cols().as_dyn_stride()).into_col_shape(A.ncols())
777		}
778	}
779	impl<
780		T: Conjugate,
781		Dim: Shape,
782		Stride: (crate::Stride),
783		Inner: (for<'a> Reborrow<'a, Target = diag::Ref<'a, T, Dim, Stride>>),
784	> Neg for diag::generic::Diag<Inner>
785	{
786		type Output = Diag<T::Canonical, Dim>;
787
788		fn neg(self) {
789			#[track_caller]
790			fn imp<T: Conjugate>(A: ColRef<'_, T>) -> Col<T::Canonical> {
791				-A
792			}
793			let A = self.rb().column_vector();
794			imp(A.as_dyn_rows().as_dyn_stride())
795				.into_row_shape(A.nrows())
796				.into_diagonal()
797		}
798	}
799});
800#[inline]
801fn add_fn<
802	LhsT: Conjugate<Canonical: ComplexField>,
803	RhsT: Conjugate<Canonical = LhsT::Canonical>,
804>()
805-> impl FnMut(linalg::zip::Zip<&LhsT, linalg::zip::Last<&RhsT>>) -> LhsT::Canonical
806{
807	#[inline(always)]
808	move |unzip!(a, b)| Conj::apply(a) + Conj::apply(b)
809}
810#[inline]
811fn sub_fn<
812	LhsT: Conjugate<Canonical: ComplexField>,
813	RhsT: Conjugate<Canonical = LhsT::Canonical>,
814>()
815-> impl FnMut(linalg::zip::Zip<&LhsT, linalg::zip::Last<&RhsT>>) -> LhsT::Canonical
816{
817	#[inline(always)]
818	move |unzip!(a, b)| Conj::apply(a) - Conj::apply(b)
819}
820#[inline]
821fn mul_fn<
822	LhsT: Conjugate<Canonical: ComplexField>,
823	RhsT: Conjugate<Canonical = LhsT::Canonical>,
824>()
825-> impl FnMut(linalg::zip::Zip<&LhsT, linalg::zip::Last<&RhsT>>) -> LhsT::Canonical
826{
827	#[inline(always)]
828	move |unzip!(a, b)| Conj::apply(a) * Conj::apply(b)
829}
830#[inline]
831fn neg_fn<LhsT: Conjugate<Canonical: ComplexField>>()
832-> impl FnMut(linalg::zip::Last<&LhsT>) -> LhsT::Canonical {
833	#[inline(always)]
834	move |unzip!(a)| -Conj::apply(a)
835}
836#[inline]
837fn add_assign_fn<LhsT: ComplexField, RhsT: Conjugate<Canonical = LhsT>>()
838-> impl FnMut(linalg::zip::Zip<&mut LhsT, linalg::zip::Last<&RhsT>>) {
839	#[inline(always)]
840	move |unzip!(a, b)| *a = Conj::apply(a) + Conj::apply(b)
841}
842#[inline]
843fn sub_assign_fn<LhsT: ComplexField, RhsT: Conjugate<Canonical = LhsT>>()
844-> impl FnMut(linalg::zip::Zip<&mut LhsT, linalg::zip::Last<&RhsT>>) {
845	#[inline(always)]
846	move |unzip!(a, b)| *a = Conj::apply(a) - Conj::apply(b)
847}
848mod matmul {
849	use super::*;
850	use crate::assert;
851	impl_binop!({
852		impl<
853			T: ComplexField,
854			Rows: Shape,
855			Cols: Shape,
856			Depth: Shape,
857			LT: (Conjugate<Canonical = T>),
858			LRStride: Stride,
859			LCStride: Stride,
860			RT: (Conjugate<Canonical = T>),
861			RRStride: Stride,
862			RCStride: Stride,
863			L: (for<'a> Reborrow<
864					'a,
865					Target = mat::Ref<'a, LT, Rows, Depth, LRStride, LCStride>,
866				>),
867			R: (for<'a> Reborrow<
868					'a,
869					Target = mat::Ref<'a, RT, Depth, Cols, RRStride, RCStride>,
870				>),
871		> Mul<mat::generic::Mat<R>> for mat::generic::Mat<L>
872		{
873			type Output = Mat<T, Rows, Cols>;
874
875			fn mul(self, rhs: _) {
876				#[track_caller]
877				fn imp<
878					T: ComplexField,
879					LT: Conjugate<Canonical = T>,
880					RT: Conjugate<Canonical = T>,
881				>(
882					lhs: MatRef<'_, LT>,
883					rhs: MatRef<'_, RT>,
884				) -> Mat<T> {
885					assert!(lhs.ncols() == rhs.nrows());
886					let mut out = Mat::zeros(lhs.nrows(), rhs.ncols());
887					crate::linalg::matmul::matmul(
888						out.as_mut(),
889						Accum::Replace,
890						lhs,
891						rhs,
892						T::one_impl(),
893						Par::Seq,
894					);
895					out
896				}
897				let lhs = self.rb();
898				let rhs = rhs.rb();
899				imp(lhs.as_dyn().as_dyn_stride(), rhs.as_dyn().as_dyn_stride())
900					.into_shape(lhs.nrows(), rhs.ncols())
901			}
902		}
903		impl<
904			T: ComplexField,
905			Rows: Shape,
906			Cols: Shape,
907			LT: (Conjugate<Canonical = T>),
908			LRStride: Stride,
909			LCStride: Stride,
910			RT: (Conjugate<Canonical = T>),
911			RRStride: Stride,
912			L: (for<'a> Reborrow<
913					'a,
914					Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
915				>),
916			R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Cols, RRStride>>),
917		> Mul<col::generic::Col<R>> for mat::generic::Mat<L>
918		{
919			type Output = Col<T, Rows>;
920
921			fn mul(self, rhs: _) {
922				#[track_caller]
923				fn imp<
924					T: ComplexField,
925					LT: Conjugate<Canonical = T>,
926					RT: Conjugate<Canonical = T>,
927				>(
928					lhs: MatRef<'_, LT>,
929					rhs: ColRef<'_, RT>,
930				) -> Col<T> {
931					assert!(lhs.ncols() == rhs.nrows());
932					let mut out = Col::zeros(lhs.nrows());
933					crate::linalg::matmul::matmul(
934						out.as_mut(),
935						Accum::Replace,
936						lhs,
937						rhs,
938						T::one_impl(),
939						Par::Seq,
940					);
941					out
942				}
943				let lhs = self.rb();
944				let rhs = rhs.rb();
945				imp(
946					lhs.as_dyn().as_dyn_stride(),
947					rhs.as_dyn_rows().as_dyn_stride(),
948				)
949				.into_row_shape(lhs.nrows())
950			}
951		}
952		impl<
953			T: ComplexField,
954			Rows: Shape,
955			Cols: Shape,
956			LT: (Conjugate<Canonical = T>),
957			LCStride: Stride,
958			RT: (Conjugate<Canonical = T>),
959			RRStride: Stride,
960			RCStride: Stride,
961			L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Rows, LCStride>>),
962			R: (for<'a> Reborrow<
963					'a,
964					Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
965				>),
966		> Mul<mat::generic::Mat<R>> for row::generic::Row<L>
967		{
968			type Output = Row<T, Cols>;
969
970			fn mul(self, rhs: _) {
971				#[track_caller]
972				fn imp<
973					T: ComplexField,
974					LT: Conjugate<Canonical = T>,
975					RT: Conjugate<Canonical = T>,
976				>(
977					lhs: RowRef<'_, LT>,
978					rhs: MatRef<'_, RT>,
979				) -> Row<T> {
980					assert!(lhs.ncols() == rhs.nrows());
981					let mut out = Row::zeros(rhs.ncols());
982					crate::linalg::matmul::matmul(
983						out.as_mut(),
984						Accum::Replace,
985						lhs,
986						rhs,
987						T::one_impl(),
988						Par::Seq,
989					);
990					out
991				}
992				let lhs = self.rb();
993				let rhs = rhs.rb();
994				imp(
995					lhs.as_dyn_cols().as_dyn_stride(),
996					rhs.as_dyn().as_dyn_stride(),
997				)
998				.into_col_shape(rhs.ncols())
999			}
1000		}
1001		impl<
1002			T: ComplexField,
1003			Dim: Shape,
1004			LT: (Conjugate<Canonical = T>),
1005			LCStride: Stride,
1006			RT: (Conjugate<Canonical = T>),
1007			RRStride: Stride,
1008			L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Dim, LCStride>>),
1009			R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Dim, RRStride>>),
1010		> Mul<col::generic::Col<R>> for row::generic::Row<L>
1011		{
1012			type Output = T;
1013
1014			fn mul(self, rhs: _) {
1015				#[track_caller]
1016				fn imp<
1017					T: ComplexField,
1018					LT: Conjugate<Canonical = T>,
1019					RT: Conjugate<Canonical = T>,
1020				>(
1021					lhs: RowRef<'_, LT>,
1022					rhs: ColRef<'_, RT>,
1023				) -> T {
1024					assert!(lhs.ncols() == rhs.nrows());
1025					let mut out = [[zero::<T>()]];
1026					crate::linalg::matmul::matmul(
1027						MatMut::from_row_major_array_mut(&mut out),
1028						Accum::Replace,
1029						lhs.as_mat(),
1030						rhs.as_mat(),
1031						T::one_impl(),
1032						Par::Seq,
1033					);
1034					let [[out]] = out;
1035					out
1036				}
1037				let lhs = self.rb();
1038				let rhs = rhs.rb();
1039				imp(
1040					lhs.as_dyn_cols().as_dyn_stride(),
1041					rhs.as_dyn_rows().as_dyn_stride(),
1042				)
1043			}
1044		}
1045		impl<
1046			T: ComplexField,
1047			Rows: Shape,
1048			Cols: Shape,
1049			LT: (Conjugate<Canonical = T>),
1050			LRStride: Stride,
1051			RT: (Conjugate<Canonical = T>),
1052			RCStride: Stride,
1053			L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
1054			R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
1055		> Mul<row::generic::Row<R>> for col::generic::Col<L>
1056		{
1057			type Output = Mat<T, Rows, Cols>;
1058
1059			fn mul(self, rhs: _) {
1060				#[track_caller]
1061				fn imp<
1062					T: ComplexField,
1063					LT: Conjugate<Canonical = T>,
1064					RT: Conjugate<Canonical = T>,
1065				>(
1066					lhs: ColRef<'_, LT>,
1067					rhs: RowRef<'_, RT>,
1068				) -> Mat<T> {
1069					assert!(lhs.ncols() == rhs.nrows());
1070					let mut out = Mat::zeros(lhs.nrows(), rhs.ncols());
1071					crate::linalg::matmul::matmul(
1072						out.rb_mut(),
1073						Accum::Replace,
1074						lhs,
1075						rhs,
1076						T::one_impl(),
1077						Par::Seq,
1078					);
1079					out
1080				}
1081				let lhs = self.rb();
1082				let rhs = rhs.rb();
1083				imp(
1084					lhs.as_dyn_rows().as_dyn_stride(),
1085					rhs.as_dyn_cols().as_dyn_stride(),
1086				)
1087				.into_shape(lhs.nrows(), rhs.ncols())
1088			}
1089		}
1090		impl<
1091			T: ComplexField,
1092			Dim: Shape,
1093			Cols: Shape,
1094			LT: (Conjugate<Canonical = T>),
1095			LStride: Stride,
1096			RT: (Conjugate<Canonical = T>),
1097			RRStride: Stride,
1098			RCStride: Stride,
1099			L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
1100			R: (for<'a> Reborrow<
1101					'a,
1102					Target = mat::Ref<'a, RT, Dim, Cols, RRStride, RCStride>,
1103				>),
1104		> Mul<mat::generic::Mat<R>> for diag::generic::Diag<L>
1105		{
1106			type Output = Mat<T, Dim, Cols>;
1107
1108			fn mul(self, rhs: _) {
1109				#[track_caller]
1110				fn imp<
1111					T: ComplexField,
1112					LT: Conjugate<Canonical = T>,
1113					RT: Conjugate<Canonical = T>,
1114				>(
1115					lhs: ColRef<'_, LT>,
1116					rhs: MatRef<'_, RT>,
1117				) -> Mat<T> {
1118					let lhs_dim = lhs.nrows();
1119					let rhs_nrows = rhs.nrows();
1120					assert!(lhs_dim == rhs_nrows);
1121					Mat::from_fn(rhs.nrows(), rhs.ncols(), |i, j| {
1122						Conj::apply(lhs.at(i)) * Conj::apply(rhs.at(i, j))
1123					})
1124				}
1125				let lhs = self.rb();
1126				let rhs = rhs.rb();
1127				imp(
1128					lhs.column_vector().as_dyn_rows().as_dyn_stride(),
1129					rhs.as_dyn().as_dyn_stride(),
1130				)
1131				.into_shape(rhs.nrows(), rhs.ncols())
1132			}
1133		}
1134		impl<
1135			T: ComplexField,
1136			Dim: Shape,
1137			LT: (Conjugate<Canonical = T>),
1138			LStride: Stride,
1139			RT: (Conjugate<Canonical = T>),
1140			RRStride: Stride,
1141			L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
1142			R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Dim, RRStride>>),
1143		> Mul<col::generic::Col<R>> for diag::generic::Diag<L>
1144		{
1145			type Output = Col<T, Dim>;
1146
1147			fn mul(self, rhs: _) {
1148				#[track_caller]
1149				fn imp<
1150					T: ComplexField,
1151					LT: Conjugate<Canonical = T>,
1152					RT: Conjugate<Canonical = T>,
1153				>(
1154					lhs: ColRef<'_, LT>,
1155					rhs: ColRef<'_, RT>,
1156				) -> Col<T> {
1157					let lhs_dim = lhs.nrows();
1158					let rhs_nrows = rhs.nrows();
1159					assert!(lhs_dim == rhs_nrows);
1160					zip!(lhs, rhs).map(mul_fn::<LT, RT>())
1161				}
1162				let lhs = self.rb();
1163				let rhs = rhs.rb();
1164				imp(
1165					lhs.column_vector().as_dyn_rows().as_dyn_stride(),
1166					rhs.as_dyn_rows().as_dyn_stride(),
1167				)
1168				.into_row_shape(rhs.nrows())
1169			}
1170		}
1171		impl<
1172			T: ComplexField,
1173			Dim: Shape,
1174			Rows: Shape,
1175			LT: (Conjugate<Canonical = T>),
1176			LRStride: Stride,
1177			LCStride: Stride,
1178			RT: (Conjugate<Canonical = T>),
1179			RStride: Stride,
1180			L: (for<'a> Reborrow<
1181					'a,
1182					Target = mat::Ref<'a, LT, Rows, Dim, LRStride, LCStride>,
1183				>),
1184			R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
1185		> Mul<diag::generic::Diag<R>> for mat::generic::Mat<L>
1186		{
1187			type Output = Mat<T, Rows, Dim>;
1188
1189			fn mul(self, rhs: _) {
1190				#[track_caller]
1191				fn imp<
1192					T: ComplexField,
1193					LT: Conjugate<Canonical = T>,
1194					RT: Conjugate<Canonical = T>,
1195				>(
1196					lhs: MatRef<'_, LT>,
1197					rhs: ColRef<'_, RT>,
1198				) -> Mat<T> {
1199					let lhs_ncols = lhs.ncols();
1200					let rhs_dim = rhs.nrows();
1201					assert!(lhs_ncols == rhs_dim);
1202					let mut f = mul_fn::<LT, RT>();
1203					Mat::from_fn(lhs.nrows(), lhs.ncols(), |i, j| {
1204						f(linalg::zip::Zip(
1205							lhs.at(i, j),
1206							linalg::zip::Last(rhs.at(j)),
1207						))
1208					})
1209				}
1210				let lhs = self.rb();
1211				let rhs = rhs.rb();
1212				imp(
1213					lhs.as_dyn().as_dyn_stride(),
1214					rhs.column_vector().as_dyn_rows().as_dyn_stride(),
1215				)
1216				.into_shape(lhs.nrows(), lhs.ncols())
1217			}
1218		}
1219		impl<
1220			T: ComplexField,
1221			Dim: Shape,
1222			LT: (Conjugate<Canonical = T>),
1223			LCStride: Stride,
1224			RT: (Conjugate<Canonical = T>),
1225			RStride: Stride,
1226			L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Dim, LCStride>>),
1227			R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
1228		> Mul<diag::generic::Diag<R>> for row::generic::Row<L>
1229		{
1230			type Output = Row<T, Dim>;
1231
1232			fn mul(self, rhs: _) {
1233				#[track_caller]
1234				fn imp<
1235					T: ComplexField,
1236					LT: Conjugate<Canonical = T>,
1237					RT: Conjugate<Canonical = T>,
1238				>(
1239					lhs: RowRef<'_, LT>,
1240					rhs: ColRef<'_, RT>,
1241				) -> Row<T> {
1242					let lhs_ncols = lhs.ncols();
1243					let rhs_dim = rhs.nrows();
1244					assert!(lhs_ncols == rhs_dim);
1245					(rhs.as_diagonal() * lhs.transpose()).into_transpose()
1246				}
1247				let lhs = self.rb();
1248				let rhs = rhs.rb();
1249				imp(
1250					lhs.as_dyn_cols().as_dyn_stride(),
1251					rhs.column_vector().as_dyn_rows().as_dyn_stride(),
1252				)
1253				.into_col_shape(lhs.ncols())
1254			}
1255		}
1256		impl<
1257			T: ComplexField,
1258			Dim: Shape,
1259			LT: (Conjugate<Canonical = T>),
1260			LStride: Stride,
1261			RT: (Conjugate<Canonical = T>),
1262			RStride: Stride,
1263			L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
1264			R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
1265		> Mul<diag::generic::Diag<R>> for diag::generic::Diag<L>
1266		{
1267			type Output = Diag<T, Dim>;
1268
1269			fn mul(self, rhs: _) {
1270				#[track_caller]
1271				fn imp<
1272					T: ComplexField,
1273					LT: Conjugate<Canonical = T>,
1274					RT: Conjugate<Canonical = T>,
1275				>(
1276					lhs: ColRef<'_, LT>,
1277					rhs: ColRef<'_, RT>,
1278				) -> Col<T> {
1279					let lhs_dim = lhs.nrows();
1280					let rhs_dim = rhs.nrows();
1281					assert!(lhs_dim == rhs_dim);
1282					lhs.as_diagonal() * rhs
1283				}
1284				let lhs = self.rb().column_vector();
1285				let rhs = rhs.rb().column_vector();
1286				imp(
1287					lhs.as_dyn_rows().as_dyn_stride(),
1288					rhs.as_dyn_rows().as_dyn_stride(),
1289				)
1290				.into_row_shape(lhs.nrows())
1291				.into_diagonal()
1292			}
1293		}
1294	});
1295}
1296impl_binop!({
1297	impl<
1298		I: Index,
1299		N: Shape,
1300		L: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, N>>),
1301		R: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, N>>),
1302	> Mul<perm::generic::Perm<R>> for perm::generic::Perm<L>
1303	{
1304		type Output = Perm<I, N>;
1305
1306		fn mul(self, rhs: _) {
1307			#[track_caller]
1308			fn imp<I: Index>(
1309				lhs: PermRef<'_, I>,
1310				rhs: PermRef<'_, I>,
1311			) -> Perm<I> {
1312				assert!(lhs.len() == rhs.len());
1313				let truncate = <I::Signed as SignedIndex>::truncate;
1314				let mut fwd =
1315					alloc::vec![I::from_signed(truncate(0)); lhs.len()]
1316						.into_boxed_slice();
1317				let mut inv =
1318					alloc::vec![I::from_signed(truncate(0)); lhs.len()]
1319						.into_boxed_slice();
1320				for (fwd, rhs) in fwd.iter_mut().zip(rhs.arrays().0) {
1321					*fwd = lhs.arrays().0[rhs.to_signed().zx()];
1322				}
1323				for (i, fwd) in fwd.iter().enumerate() {
1324					inv[fwd.to_signed().zx()] =
1325						I::from_signed(I::Signed::truncate(i));
1326				}
1327				Perm::new_checked(fwd, inv, lhs.len())
1328			}
1329			let lhs = self.rb();
1330			let rhs = rhs.rb();
1331			let N = lhs.len();
1332			let n = N.unbound();
1333			imp(lhs.as_shape(n), rhs.as_shape(n)).into_shape(N)
1334		}
1335	}
1336	impl<
1337		I: Index,
1338		T: ComplexField,
1339		Rows: Shape,
1340		Cols: Shape,
1341		RT: (Conjugate<Canonical = T>),
1342		RRStride: Stride,
1343		RCStride: Stride,
1344		L: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Rows>>),
1345		R: (for<'a> Reborrow<
1346				'a,
1347				Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
1348			>),
1349	> Mul<mat::generic::Mat<R>> for perm::generic::Perm<L>
1350	{
1351		type Output = Mat<T, Rows, Cols>;
1352
1353		fn mul(self, rhs: _) {
1354			#[track_caller]
1355			fn imp<I: Index, T: ComplexField, RT: Conjugate<Canonical = T>>(
1356				lhs: PermRef<'_, I>,
1357				rhs: MatRef<'_, RT>,
1358			) -> Mat<T> {
1359				with_dim!(M, rhs.nrows());
1360				with_dim!(N, rhs.ncols());
1361				let rhs = rhs.as_shape(M, N);
1362				let lhs = lhs.as_shape(M);
1363				let mut out = Mat::zeros(rhs.nrows(), rhs.ncols());
1364				let fwd = lhs.bound_arrays().0;
1365				for j in rhs.ncols().indices() {
1366					for i in rhs.nrows().indices() {
1367						let fwd = fwd[i];
1368						let rhs = rhs.at(fwd.zx(), j);
1369						out[(i, j)] = Conj::apply(rhs);
1370					}
1371				}
1372				out.into_shape(*M, *N)
1373			}
1374			let lhs = self.rb();
1375			let rhs = rhs.rb();
1376			let m = rhs.nrows().unbound();
1377			imp(lhs.as_shape(m), rhs.as_dyn().as_dyn_stride())
1378				.into_shape(rhs.nrows(), rhs.ncols())
1379		}
1380	}
1381	impl<
1382		I: Index,
1383		T: ComplexField,
1384		Rows: Shape,
1385		RT: (Conjugate<Canonical = T>),
1386		RRStride: Stride,
1387		L: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Rows>>),
1388		R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
1389	> Mul<col::generic::Col<R>> for perm::generic::Perm<L>
1390	{
1391		type Output = Col<T, Rows>;
1392
1393		fn mul(self, rhs: _) {
1394			#[track_caller]
1395			fn imp<I: Index, T: ComplexField, RT: Conjugate<Canonical = T>>(
1396				lhs: PermRef<'_, I>,
1397				rhs: ColRef<'_, RT>,
1398			) -> Col<T> {
1399				with_dim!(M, rhs.nrows());
1400				let rhs = rhs.as_row_shape(M);
1401				let lhs = lhs.as_shape(M);
1402				let mut out = Col::zeros(rhs.nrows());
1403				let fwd = lhs.bound_arrays().0;
1404				for i in rhs.nrows().indices() {
1405					let fwd = fwd[i];
1406					let rhs = rhs.at(fwd.zx());
1407					out[i] = Conj::apply(rhs);
1408				}
1409				out.into_row_shape(*M)
1410			}
1411			let lhs = self.rb();
1412			let rhs = rhs.rb();
1413			let m = rhs.nrows().unbound();
1414			imp(lhs.as_shape(m), rhs.as_dyn_rows().as_dyn_stride())
1415				.into_row_shape(rhs.nrows())
1416		}
1417	}
1418	impl<
1419		I: Index,
1420		T: ComplexField,
1421		Rows: Shape,
1422		Cols: Shape,
1423		LT: (Conjugate<Canonical = T>),
1424		LRStride: Stride,
1425		LCStride: Stride,
1426		L: (for<'a> Reborrow<
1427				'a,
1428				Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
1429			>),
1430		R: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Cols>>),
1431	> Mul<perm::generic::Perm<R>> for mat::generic::Mat<L>
1432	{
1433		type Output = Mat<T, Rows, Cols>;
1434
1435		fn mul(self, rhs: _) {
1436			#[track_caller]
1437			fn imp<I: Index, T: ComplexField, LT: Conjugate<Canonical = T>>(
1438				lhs: MatRef<'_, LT>,
1439				rhs: PermRef<'_, I>,
1440			) -> Mat<T> {
1441				with_dim!(M, lhs.nrows());
1442				with_dim!(N, lhs.ncols());
1443				let lhs = lhs.as_shape(M, N);
1444				let rhs = rhs.as_shape(N);
1445				let mut out = Mat::zeros(M, N);
1446				let inv = rhs.bound_arrays().1;
1447				for j in N.indices() {
1448					let inv = inv[j];
1449					for i in M.indices() {
1450						let lhs = lhs.at(i, inv.zx());
1451						out[(i, j)] = Conj::apply(lhs);
1452					}
1453				}
1454				out.into_shape(*M, *N)
1455			}
1456			let lhs = self.rb();
1457			let rhs = rhs.rb();
1458			let n = lhs.ncols().unbound();
1459			imp(lhs.as_dyn().as_dyn_stride(), rhs.as_shape(n))
1460				.into_shape(lhs.nrows(), lhs.ncols())
1461		}
1462	}
1463	impl<
1464		I: Index,
1465		T: ComplexField,
1466		Cols: Shape,
1467		LT: (Conjugate<Canonical = T>),
1468		LCStride: Stride,
1469		L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
1470		R: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Cols>>),
1471	> Mul<perm::generic::Perm<R>> for row::generic::Row<L>
1472	{
1473		type Output = Row<T, Cols>;
1474
1475		fn mul(self, rhs: _) {
1476			#[track_caller]
1477			fn imp<I: Index, T: ComplexField, LT: Conjugate<Canonical = T>>(
1478				lhs: RowRef<'_, LT>,
1479				rhs: PermRef<'_, I>,
1480			) -> Row<T> {
1481				with_dim!(N, lhs.ncols());
1482				let lhs = lhs.as_col_shape(N);
1483				let rhs = rhs.as_shape(N);
1484				let mut out = Row::zeros(N);
1485				let inv = rhs.bound_arrays().1;
1486				for j in N.indices() {
1487					let inv = inv[j];
1488					let lhs = lhs.at(inv.zx());
1489					out[j] = Conj::apply(lhs);
1490				}
1491				out.into_col_shape(*N)
1492			}
1493			let lhs = self.rb();
1494			let rhs = rhs.rb();
1495			let n = lhs.ncols().unbound();
1496			imp(lhs.as_dyn_cols().as_dyn_stride(), rhs.as_shape(n))
1497				.into_col_shape(lhs.ncols())
1498		}
1499	}
1500});
1501impl_binop!({
1502	impl<
1503		T: ComplexField,
1504		Rows: Shape,
1505		Cols: Shape,
1506		LT: (Conjugate<Canonical = T>),
1507		LRStride: Stride,
1508		LCStride: Stride,
1509		L: (for<'a> Reborrow<
1510				'a,
1511				Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
1512			>),
1513	> Mul<Scale<T>> for mat::generic::Mat<L>
1514	{
1515		type Output = Mat<T, Rows, Cols>;
1516
1517		fn mul(self, rhs: _) {
1518			#[track_caller]
1519			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1520				lhs: MatRef<'_, LT>,
1521				rhs: &T,
1522			) -> Mat<T> {
1523				zip!(lhs).map(|unzip!(x)| Conj::apply(x) * rhs)
1524			}
1525			let lhs = self.rb();
1526			let rhs = &rhs.0;
1527			imp(lhs.as_dyn().as_dyn_stride(), rhs)
1528				.into_shape(lhs.nrows(), lhs.ncols())
1529		}
1530	}
1531	impl<
1532		T: ComplexField,
1533		Rows: Shape,
1534		Cols: Shape,
1535		LT: (Conjugate<Canonical = T>),
1536		LRStride: Stride,
1537		LCStride: Stride,
1538		L: (for<'a> Reborrow<
1539				'a,
1540				Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
1541			>),
1542	> Div<Scale<T>> for mat::generic::Mat<L>
1543	{
1544		type Output = Mat<T, Rows, Cols>;
1545
1546		fn div(self, rhs: _) {
1547			#[track_caller]
1548			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1549				lhs: MatRef<'_, LT>,
1550				rhs: &T,
1551			) -> Mat<T> {
1552				lhs * Scale(rhs.recip())
1553			}
1554			let lhs = self.rb();
1555			let rhs = &rhs.0;
1556			imp(lhs.as_dyn().as_dyn_stride(), rhs)
1557				.into_shape(lhs.nrows(), lhs.ncols())
1558		}
1559	}
1560	impl<
1561		T: ComplexField,
1562		Rows: Shape,
1563		Cols: Shape,
1564		RT: (Conjugate<Canonical = T>),
1565		RRStride: Stride,
1566		RCStride: Stride,
1567		R: (for<'a> Reborrow<
1568				'a,
1569				Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
1570			>),
1571	> Mul<mat::generic::Mat<R>> for Scale<T>
1572	{
1573		type Output = Mat<T, Rows, Cols>;
1574
1575		fn mul(self, rhs: _) {
1576			#[track_caller]
1577			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
1578				lhs: &T,
1579				rhs: MatRef<'_, RT>,
1580			) -> Mat<T> {
1581				zip!(rhs).map(|unzip!(x)| lhs * Conj::apply(x))
1582			}
1583			let lhs = &self.0;
1584			let rhs = rhs.rb();
1585			imp(lhs, rhs.as_dyn().as_dyn_stride())
1586				.into_shape(rhs.nrows(), rhs.ncols())
1587		}
1588	}
1589});
1590impl_binop!({
1591	impl<
1592		T: ComplexField,
1593		Rows: Shape,
1594		LT: (Conjugate<Canonical = T>),
1595		LRStride: Stride,
1596		L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
1597	> Mul<Scale<T>> for col::generic::Col<L>
1598	{
1599		type Output = Col<T, Rows>;
1600
1601		fn mul(self, rhs: _) {
1602			#[track_caller]
1603			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1604				lhs: ColRef<'_, LT>,
1605				rhs: &T,
1606			) -> Col<T> {
1607				zip!(lhs).map(|unzip!(x)| Conj::apply(x) * rhs)
1608			}
1609			let lhs = self.rb();
1610			let rhs = &rhs.0;
1611			imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
1612				.into_row_shape(lhs.nrows())
1613		}
1614	}
1615	impl<
1616		T: ComplexField,
1617		Rows: Shape,
1618		LT: (Conjugate<Canonical = T>),
1619		LRStride: Stride,
1620		L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
1621	> Div<Scale<T>> for col::generic::Col<L>
1622	{
1623		type Output = Col<T, Rows>;
1624
1625		fn div(self, rhs: _) {
1626			#[track_caller]
1627			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1628				lhs: ColRef<'_, LT>,
1629				rhs: &T,
1630			) -> Col<T> {
1631				lhs * Scale(rhs.recip())
1632			}
1633			let lhs = self.rb();
1634			let rhs = &rhs.0;
1635			imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
1636				.into_row_shape(lhs.nrows())
1637		}
1638	}
1639	impl<
1640		T: ComplexField,
1641		Rows: Shape,
1642		RT: (Conjugate<Canonical = T>),
1643		RRStride: Stride,
1644		R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
1645	> Mul<col::generic::Col<R>> for Scale<T>
1646	{
1647		type Output = Col<T, Rows>;
1648
1649		fn mul(self, rhs: _) {
1650			#[track_caller]
1651			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
1652				lhs: &T,
1653				rhs: ColRef<'_, RT>,
1654			) -> Col<T> {
1655				zip!(rhs).map(|unzip!(x)| lhs * Conj::apply(x))
1656			}
1657			let lhs = &self.0;
1658			let rhs = rhs.rb();
1659			imp(lhs, rhs.as_dyn_rows().as_dyn_stride())
1660				.into_row_shape(rhs.nrows())
1661		}
1662	}
1663});
1664impl_binop!({
1665	impl<
1666		T: ComplexField,
1667		Cols: Shape,
1668		LT: (Conjugate<Canonical = T>),
1669		LCStride: Stride,
1670		L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
1671	> Mul<Scale<T>> for row::generic::Row<L>
1672	{
1673		type Output = Row<T, Cols>;
1674
1675		fn mul(self, rhs: _) {
1676			#[track_caller]
1677			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1678				lhs: RowRef<'_, LT>,
1679				rhs: &T,
1680			) -> Row<T> {
1681				(lhs.transpose() * Scale::from_ref(rhs)).into_transpose()
1682			}
1683			let lhs = self.rb();
1684			let rhs = &rhs.0;
1685			imp(lhs.as_dyn_cols().as_dyn_stride(), rhs)
1686				.into_col_shape(lhs.ncols())
1687		}
1688	}
1689	impl<
1690		T: ComplexField,
1691		Cols: Shape,
1692		LT: (Conjugate<Canonical = T>),
1693		LCStride: Stride,
1694		L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
1695	> Div<Scale<T>> for row::generic::Row<L>
1696	{
1697		type Output = Row<T, Cols>;
1698
1699		fn div(self, rhs: _) {
1700			#[track_caller]
1701			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1702				lhs: RowRef<'_, LT>,
1703				rhs: &T,
1704			) -> Row<T> {
1705				lhs * Scale(rhs.recip())
1706			}
1707			let lhs = self.rb();
1708			let rhs = &rhs.0;
1709			imp(lhs.as_dyn_cols().as_dyn_stride(), rhs)
1710				.into_col_shape(lhs.ncols())
1711		}
1712	}
1713	impl<
1714		T: ComplexField,
1715		Cols: Shape,
1716		RT: (Conjugate<Canonical = T>),
1717		RCStride: Stride,
1718		R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
1719	> Mul<row::generic::Row<R>> for Scale<T>
1720	{
1721		type Output = Row<T, Cols>;
1722
1723		fn mul(self, rhs: _) {
1724			#[track_caller]
1725			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
1726				lhs: &T,
1727				rhs: RowRef<'_, RT>,
1728			) -> Row<T> {
1729				(Scale::from_ref(lhs) * rhs.transpose()).into_transpose()
1730			}
1731			let lhs = &self.0;
1732			let rhs = rhs.rb();
1733			imp(lhs, rhs.as_dyn_cols().as_dyn_stride())
1734				.into_col_shape(rhs.ncols())
1735		}
1736	}
1737});
1738impl_binop!({
1739	impl<
1740		T: ComplexField,
1741		Dim: Shape,
1742		LT: (Conjugate<Canonical = T>),
1743		LStride: Stride,
1744		L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
1745	> Mul<Scale<T>> for diag::generic::Diag<L>
1746	{
1747		type Output = Diag<T, Dim>;
1748
1749		fn mul(self, rhs: _) {
1750			#[track_caller]
1751			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1752				lhs: ColRef<'_, LT>,
1753				rhs: &T,
1754			) -> Col<T> {
1755				lhs * Scale::from_ref(rhs)
1756			}
1757			let lhs = self.rb().column_vector();
1758			let rhs = &rhs.0;
1759			imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
1760				.into_row_shape(lhs.nrows())
1761				.into_diagonal()
1762		}
1763	}
1764	impl<
1765		T: ComplexField,
1766		Dim: Shape,
1767		LT: (Conjugate<Canonical = T>),
1768		LStride: Stride,
1769		L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
1770	> Div<Scale<T>> for diag::generic::Diag<L>
1771	{
1772		type Output = Diag<T, Dim>;
1773
1774		fn div(self, rhs: _) {
1775			#[track_caller]
1776			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1777				lhs: ColRef<'_, LT>,
1778				rhs: &T,
1779			) -> Col<T> {
1780				lhs * Scale(rhs.recip())
1781			}
1782			let lhs = self.rb().column_vector();
1783			let rhs = &rhs.0;
1784			imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
1785				.into_row_shape(lhs.nrows())
1786				.into_diagonal()
1787		}
1788	}
1789	impl<
1790		T: ComplexField,
1791		Dim: Shape,
1792		RT: (Conjugate<Canonical = T>),
1793		RStride: Stride,
1794		R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
1795	> Mul<diag::generic::Diag<R>> for Scale<T>
1796	{
1797		type Output = Diag<T, Dim>;
1798
1799		fn mul(self, rhs: _) {
1800			#[track_caller]
1801			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
1802				lhs: &T,
1803				rhs: ColRef<'_, RT>,
1804			) -> Col<T> {
1805				Scale::from_ref(lhs) * rhs
1806			}
1807			let lhs = &self.0;
1808			let rhs = rhs.rb().column_vector();
1809			imp(lhs, rhs.as_dyn_rows().as_dyn_stride())
1810				.into_row_shape(rhs.nrows())
1811				.into_diagonal()
1812		}
1813	}
1814});
1815impl_binop!({
1816	impl<
1817		T: ComplexField,
1818		Rows: Shape,
1819		Cols: Shape,
1820		LT: (Conjugate<Canonical = T>),
1821		LRStride: Stride,
1822		LCStride: Stride,
1823		L: (for<'a> Reborrow<
1824				'a,
1825				Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
1826			>),
1827	> Mul<f64> for mat::generic::Mat<L>
1828	{
1829		type Output = Mat<T, Rows, Cols>;
1830
1831		fn mul(self, rhs: _) {
1832			#[track_caller]
1833			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1834				lhs: MatRef<'_, LT>,
1835				rhs: &T,
1836			) -> Mat<T> {
1837				lhs * Scale::from_ref(rhs)
1838			}
1839			let lhs = self.rb();
1840			let rhs = &from_f64::<T>(*rhs);
1841			imp(lhs.as_dyn().as_dyn_stride(), rhs)
1842				.into_shape(lhs.nrows(), lhs.ncols())
1843		}
1844	}
1845	impl<
1846		T: ComplexField,
1847		Rows: Shape,
1848		Cols: Shape,
1849		LT: (Conjugate<Canonical = T>),
1850		LRStride: Stride,
1851		LCStride: Stride,
1852		L: (for<'a> Reborrow<
1853				'a,
1854				Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
1855			>),
1856	> Div<f64> for mat::generic::Mat<L>
1857	{
1858		type Output = Mat<T, Rows, Cols>;
1859
1860		fn div(self, rhs: _) {
1861			#[track_caller]
1862			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1863				lhs: MatRef<'_, LT>,
1864				rhs: &T,
1865			) -> Mat<T> {
1866				lhs * Scale(rhs.recip())
1867			}
1868			let lhs = self.rb();
1869			let rhs = &from_f64::<T>(*rhs);
1870			imp(lhs.as_dyn().as_dyn_stride(), rhs)
1871				.into_shape(lhs.nrows(), lhs.ncols())
1872		}
1873	}
1874	impl<
1875		T: ComplexField,
1876		Rows: Shape,
1877		Cols: Shape,
1878		RT: (Conjugate<Canonical = T>),
1879		RRStride: Stride,
1880		RCStride: Stride,
1881		R: (for<'a> Reborrow<
1882				'a,
1883				Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
1884			>),
1885	> Mul<mat::generic::Mat<R>> for f64
1886	{
1887		type Output = Mat<T, Rows, Cols>;
1888
1889		fn mul(self, rhs: _) {
1890			#[track_caller]
1891			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
1892				lhs: &T,
1893				rhs: MatRef<'_, RT>,
1894			) -> Mat<T> {
1895				Scale::from_ref(lhs) * rhs
1896			}
1897			let lhs = &from_f64::<T>(*self);
1898			let rhs = rhs.rb();
1899			imp(lhs, rhs.as_dyn().as_dyn_stride())
1900				.into_shape(rhs.nrows(), rhs.ncols())
1901		}
1902	}
1903});
1904impl_binop!({
1905	impl<
1906		T: ComplexField,
1907		Rows: Shape,
1908		LT: (Conjugate<Canonical = T>),
1909		LRStride: Stride,
1910		L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
1911	> Mul<f64> for col::generic::Col<L>
1912	{
1913		type Output = Col<T, Rows>;
1914
1915		fn mul(self, rhs: _) {
1916			#[track_caller]
1917			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1918				lhs: ColRef<'_, LT>,
1919				rhs: &T,
1920			) -> Col<T> {
1921				lhs * Scale::from_ref(rhs)
1922			}
1923			let lhs = self.rb();
1924			let rhs = &from_f64::<T>(*rhs);
1925			imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
1926				.into_row_shape(lhs.nrows())
1927		}
1928	}
1929	impl<
1930		T: ComplexField,
1931		Rows: Shape,
1932		LT: (Conjugate<Canonical = T>),
1933		LRStride: Stride,
1934		L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
1935	> Div<f64> for col::generic::Col<L>
1936	{
1937		type Output = Col<T, Rows>;
1938
1939		fn div(self, rhs: _) {
1940			#[track_caller]
1941			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1942				lhs: ColRef<'_, LT>,
1943				rhs: &T,
1944			) -> Col<T> {
1945				lhs * Scale(rhs.recip())
1946			}
1947			let lhs = self.rb();
1948			let rhs = &from_f64::<T>(*rhs);
1949			imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
1950				.into_row_shape(lhs.nrows())
1951		}
1952	}
1953	impl<
1954		T: ComplexField,
1955		Rows: Shape,
1956		RT: (Conjugate<Canonical = T>),
1957		RRStride: Stride,
1958		R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
1959	> Mul<col::generic::Col<R>> for f64
1960	{
1961		type Output = Col<T, Rows>;
1962
1963		fn mul(self, rhs: _) {
1964			#[track_caller]
1965			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
1966				lhs: &T,
1967				rhs: ColRef<'_, RT>,
1968			) -> Col<T> {
1969				Scale::from_ref(lhs) * rhs
1970			}
1971			let lhs = &from_f64::<T>(*self);
1972			let rhs = rhs.rb();
1973			imp(lhs, rhs.as_dyn_rows().as_dyn_stride())
1974				.into_row_shape(rhs.nrows())
1975		}
1976	}
1977});
1978impl_binop!({
1979	impl<
1980		T: ComplexField,
1981		Cols: Shape,
1982		LT: (Conjugate<Canonical = T>),
1983		LCStride: Stride,
1984		L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
1985	> Mul<f64> for row::generic::Row<L>
1986	{
1987		type Output = Row<T, Cols>;
1988
1989		fn mul(self, rhs: _) {
1990			#[track_caller]
1991			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
1992				lhs: RowRef<'_, LT>,
1993				rhs: &T,
1994			) -> Row<T> {
1995				(lhs.transpose() * Scale::from_ref(rhs)).into_transpose()
1996			}
1997			let lhs = self.rb();
1998			let rhs = &from_f64::<T>(*rhs);
1999			imp(lhs.as_dyn_cols().as_dyn_stride(), rhs)
2000				.into_col_shape(lhs.ncols())
2001		}
2002	}
2003	impl<
2004		T: ComplexField,
2005		Cols: Shape,
2006		LT: (Conjugate<Canonical = T>),
2007		LCStride: Stride,
2008		L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
2009	> Div<f64> for row::generic::Row<L>
2010	{
2011		type Output = Row<T, Cols>;
2012
2013		fn div(self, rhs: _) {
2014			#[track_caller]
2015			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
2016				lhs: RowRef<'_, LT>,
2017				rhs: &T,
2018			) -> Row<T> {
2019				lhs * Scale(rhs.recip())
2020			}
2021			let lhs = self.rb();
2022			let rhs = &from_f64::<T>(*rhs);
2023			imp(lhs.as_dyn_cols().as_dyn_stride(), rhs)
2024				.into_col_shape(lhs.ncols())
2025		}
2026	}
2027	impl<
2028		T: ComplexField,
2029		Cols: Shape,
2030		RT: (Conjugate<Canonical = T>),
2031		RCStride: Stride,
2032		R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
2033	> Mul<row::generic::Row<R>> for f64
2034	{
2035		type Output = Row<T, Cols>;
2036
2037		fn mul(self, rhs: _) {
2038			#[track_caller]
2039			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
2040				lhs: &T,
2041				rhs: RowRef<'_, RT>,
2042			) -> Row<T> {
2043				(Scale::from_ref(lhs) * rhs.transpose()).into_transpose()
2044			}
2045			let lhs = &from_f64::<T>(*self);
2046			let rhs = rhs.rb();
2047			imp(lhs, rhs.as_dyn_cols().as_dyn_stride())
2048				.into_col_shape(rhs.ncols())
2049		}
2050	}
2051});
2052impl_binop!({
2053	impl<
2054		T: ComplexField,
2055		Dim: Shape,
2056		LT: (Conjugate<Canonical = T>),
2057		LStride: Stride,
2058		L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
2059	> Mul<f64> for diag::generic::Diag<L>
2060	{
2061		type Output = Diag<T, Dim>;
2062
2063		fn mul(self, rhs: _) {
2064			#[track_caller]
2065			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
2066				lhs: ColRef<'_, LT>,
2067				rhs: &T,
2068			) -> Col<T> {
2069				lhs * Scale::from_ref(rhs)
2070			}
2071			let lhs = self.rb().column_vector();
2072			let rhs = &from_f64::<T>(*rhs);
2073			imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
2074				.into_row_shape(lhs.nrows())
2075				.into_diagonal()
2076		}
2077	}
2078	impl<
2079		T: ComplexField,
2080		Dim: Shape,
2081		LT: (Conjugate<Canonical = T>),
2082		LStride: Stride,
2083		L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
2084	> Div<f64> for diag::generic::Diag<L>
2085	{
2086		type Output = Diag<T, Dim>;
2087
2088		fn div(self, rhs: _) {
2089			#[track_caller]
2090			fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
2091				lhs: ColRef<'_, LT>,
2092				rhs: &T,
2093			) -> Col<T> {
2094				lhs * Scale(rhs.recip())
2095			}
2096			let lhs = self.rb().column_vector();
2097			let rhs = &from_f64::<T>(*rhs);
2098			imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
2099				.into_row_shape(lhs.nrows())
2100				.into_diagonal()
2101		}
2102	}
2103	impl<
2104		T: ComplexField,
2105		Dim: Shape,
2106		RT: (Conjugate<Canonical = T>),
2107		RStride: Stride,
2108		R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
2109	> Mul<diag::generic::Diag<R>> for f64
2110	{
2111		type Output = Diag<T, Dim>;
2112
2113		fn mul(self, rhs: _) {
2114			#[track_caller]
2115			fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
2116				lhs: &T,
2117				rhs: ColRef<'_, RT>,
2118			) -> Col<T> {
2119				Scale::from_ref(lhs) * rhs
2120			}
2121			let lhs = &from_f64::<T>(*self);
2122			let rhs = rhs.rb().column_vector();
2123			imp(lhs, rhs.as_dyn_rows().as_dyn_stride())
2124				.into_row_shape(rhs.nrows())
2125				.into_diagonal()
2126		}
2127	}
2128});
2129impl_op_assign!({
2130	impl<
2131		T: ComplexField,
2132		Rows: Shape,
2133		Cols: Shape,
2134		LRStride: Stride,
2135		LCStride: Stride,
2136		L: (for<'a> ReborrowMut<
2137				'a,
2138				Target = mat::Mut<'a, T, Rows, Cols, LRStride, LCStride>,
2139			>),
2140	> MulAssign<Scale<T>> for mat::generic::Mat<L>
2141	{
2142		fn mul_assign(&mut self, rhs: _) {
2143			#[track_caller]
2144			fn imp<T: ComplexField>(lhs: MatMut<'_, T>, rhs: &T) {
2145				zip!(lhs).for_each(|unzip!(x)| *x *= rhs)
2146			}
2147			let lhs = self.rb_mut();
2148			let rhs = &rhs.0;
2149			imp(lhs.as_dyn_mut().as_dyn_stride_mut(), rhs)
2150		}
2151	}
2152	impl<
2153		T: ComplexField,
2154		Rows: Shape,
2155		Cols: Shape,
2156		LRStride: Stride,
2157		LCStride: Stride,
2158		L: (for<'a> ReborrowMut<
2159				'a,
2160				Target = mat::Mut<'a, T, Rows, Cols, LRStride, LCStride>,
2161			>),
2162	> DivAssign<Scale<T>> for mat::generic::Mat<L>
2163	{
2164		fn div_assign(&mut self, rhs: _) {
2165			#[track_caller]
2166			fn imp<T: ComplexField>(mut lhs: MatMut<'_, T>, rhs: &T) {
2167				lhs *= Scale(rhs.recip());
2168			}
2169			let lhs = self.rb_mut();
2170			let rhs = &rhs.0;
2171			imp(lhs.as_dyn_mut().as_dyn_stride_mut(), rhs)
2172		}
2173	}
2174});
2175impl_op_assign!({
2176	impl<
2177		T: ComplexField,
2178		Rows: Shape,
2179		LRStride: Stride,
2180		L: (for<'a> ReborrowMut<'a, Target = col::Mut<'a, T, Rows, LRStride>>),
2181	> MulAssign<Scale<T>> for col::generic::Col<L>
2182	{
2183		fn mul_assign(&mut self, rhs: _) {
2184			#[track_caller]
2185			fn imp<T: ComplexField>(lhs: ColMut<'_, T>, rhs: &T) {
2186				zip!(lhs).for_each(|unzip!(x)| *x *= rhs)
2187			}
2188			let lhs = self.rb_mut();
2189			let rhs = &rhs.0;
2190			imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
2191		}
2192	}
2193	impl<
2194		T: ComplexField,
2195		Rows: Shape,
2196		LRStride: Stride,
2197		L: (for<'a> ReborrowMut<'a, Target = col::Mut<'a, T, Rows, LRStride>>),
2198	> DivAssign<Scale<T>> for col::generic::Col<L>
2199	{
2200		fn div_assign(&mut self, rhs: _) {
2201			#[track_caller]
2202			fn imp<T: ComplexField>(mut lhs: ColMut<'_, T>, rhs: &T) {
2203				lhs *= Scale(rhs.recip());
2204			}
2205			let lhs = self.rb_mut();
2206			let rhs = &rhs.0;
2207			imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
2208		}
2209	}
2210});
2211impl_op_assign!({
2212	impl<
2213		T: ComplexField,
2214		Cols: Shape,
2215		LCStride: Stride,
2216		L: (for<'a> ReborrowMut<'a, Target = row::Mut<'a, T, Cols, LCStride>>),
2217	> MulAssign<Scale<T>> for row::generic::Row<L>
2218	{
2219		fn mul_assign(&mut self, rhs: _) {
2220			#[track_caller]
2221			fn imp<T: ComplexField>(lhs: RowMut<'_, T>, rhs: &T) {
2222				let mut lhs = lhs.transpose_mut();
2223				lhs *= Scale::from_ref(rhs);
2224			}
2225			let lhs = self.rb_mut();
2226			let rhs = &rhs.0;
2227			imp(lhs.as_dyn_cols_mut().as_dyn_stride_mut(), rhs)
2228		}
2229	}
2230	impl<
2231		T: ComplexField,
2232		Cols: Shape,
2233		LCStride: Stride,
2234		L: (for<'a> ReborrowMut<'a, Target = row::Mut<'a, T, Cols, LCStride>>),
2235	> DivAssign<Scale<T>> for row::generic::Row<L>
2236	{
2237		fn div_assign(&mut self, rhs: _) {
2238			#[track_caller]
2239			fn imp<T: ComplexField>(mut lhs: RowMut<'_, T>, rhs: &T) {
2240				lhs *= Scale(rhs.recip());
2241			}
2242			let lhs = self.rb_mut();
2243			let rhs = &rhs.0;
2244			imp(lhs.as_dyn_cols_mut().as_dyn_stride_mut(), rhs)
2245		}
2246	}
2247});
2248impl_op_assign!({
2249	impl<
2250		T: ComplexField,
2251		Cols: Shape,
2252		LCStride: Stride,
2253		L: (for<'a> ReborrowMut<'a, Target = diag::Mut<'a, T, Cols, LCStride>>),
2254	> MulAssign<Scale<T>> for diag::generic::Diag<L>
2255	{
2256		fn mul_assign(&mut self, rhs: _) {
2257			#[track_caller]
2258			fn imp<T: ComplexField>(mut lhs: ColMut<'_, T>, rhs: &T) {
2259				lhs *= Scale::from_ref(rhs);
2260			}
2261			let lhs = self.rb_mut().column_vector_mut();
2262			let rhs = &rhs.0;
2263			imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
2264		}
2265	}
2266	impl<
2267		T: ComplexField,
2268		Cols: Shape,
2269		LCStride: Stride,
2270		L: (for<'a> ReborrowMut<'a, Target = diag::Mut<'a, T, Cols, LCStride>>),
2271	> DivAssign<Scale<T>> for diag::generic::Diag<L>
2272	{
2273		fn div_assign(&mut self, rhs: _) {
2274			#[track_caller]
2275			fn imp<T: ComplexField>(mut lhs: ColMut<'_, T>, rhs: &T) {
2276				lhs *= Scale(rhs.recip());
2277			}
2278			let lhs = self.rb_mut().column_vector_mut();
2279			let rhs = &rhs.0;
2280			imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
2281		}
2282	}
2283});
2284impl_op_assign!({
2285	impl<
2286		T: ComplexField,
2287		Rows: Shape,
2288		Cols: Shape,
2289		LRStride: Stride,
2290		LCStride: Stride,
2291		L: (for<'a> ReborrowMut<
2292				'a,
2293				Target = mat::Mut<'a, T, Rows, Cols, LRStride, LCStride>,
2294			>),
2295	> MulAssign<f64> for mat::generic::Mat<L>
2296	{
2297		fn mul_assign(&mut self, rhs: _) {
2298			#[track_caller]
2299			fn imp<T: ComplexField>(lhs: MatMut<'_, T>, rhs: &T) {
2300				zip!(lhs).for_each(|unzip!(x)| *x *= rhs)
2301			}
2302			let lhs = self.rb_mut();
2303			let rhs = &from_f64::<T>(*rhs);
2304			imp(lhs.as_dyn_mut().as_dyn_stride_mut(), rhs)
2305		}
2306	}
2307	impl<
2308		T: ComplexField,
2309		Rows: Shape,
2310		Cols: Shape,
2311		LRStride: Stride,
2312		LCStride: Stride,
2313		L: (for<'a> ReborrowMut<
2314				'a,
2315				Target = mat::Mut<'a, T, Rows, Cols, LRStride, LCStride>,
2316			>),
2317	> DivAssign<f64> for mat::generic::Mat<L>
2318	{
2319		fn div_assign(&mut self, rhs: _) {
2320			#[track_caller]
2321			fn imp<T: ComplexField>(mut lhs: MatMut<'_, T>, rhs: &T) {
2322				lhs *= Scale(rhs.recip());
2323			}
2324			let lhs = self.rb_mut();
2325			let rhs = &from_f64::<T>(*rhs);
2326			imp(lhs.as_dyn_mut().as_dyn_stride_mut(), rhs)
2327		}
2328	}
2329});
2330impl_op_assign!({
2331	impl<
2332		T: ComplexField,
2333		Rows: Shape,
2334		LRStride: Stride,
2335		L: (for<'a> ReborrowMut<'a, Target = col::Mut<'a, T, Rows, LRStride>>),
2336	> MulAssign<f64> for col::generic::Col<L>
2337	{
2338		fn mul_assign(&mut self, rhs: _) {
2339			#[track_caller]
2340			fn imp<T: ComplexField>(lhs: ColMut<'_, T>, rhs: &T) {
2341				zip!(lhs).for_each(|unzip!(x)| *x *= rhs)
2342			}
2343			let lhs = self.rb_mut();
2344			let rhs = &from_f64::<T>(*rhs);
2345			imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
2346		}
2347	}
2348	impl<
2349		T: ComplexField,
2350		Rows: Shape,
2351		LRStride: Stride,
2352		L: (for<'a> ReborrowMut<'a, Target = col::Mut<'a, T, Rows, LRStride>>),
2353	> DivAssign<f64> for col::generic::Col<L>
2354	{
2355		fn div_assign(&mut self, rhs: _) {
2356			#[track_caller]
2357			fn imp<T: ComplexField>(mut lhs: ColMut<'_, T>, rhs: &T) {
2358				lhs *= Scale(rhs.recip());
2359			}
2360			let lhs = self.rb_mut();
2361			let rhs = &from_f64::<T>(*rhs);
2362			imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
2363		}
2364	}
2365});
2366impl_op_assign!({
2367	impl<
2368		T: ComplexField,
2369		Cols: Shape,
2370		LCStride: Stride,
2371		L: (for<'a> ReborrowMut<'a, Target = row::Mut<'a, T, Cols, LCStride>>),
2372	> MulAssign<f64> for row::generic::Row<L>
2373	{
2374		fn mul_assign(&mut self, rhs: _) {
2375			#[track_caller]
2376			fn imp<T: ComplexField>(lhs: RowMut<'_, T>, rhs: &T) {
2377				let mut lhs = lhs.transpose_mut();
2378				lhs *= Scale::from_ref(rhs);
2379			}
2380			let lhs = self.rb_mut();
2381			let rhs = &from_f64::<T>(*rhs);
2382			imp(lhs.as_dyn_cols_mut().as_dyn_stride_mut(), rhs)
2383		}
2384	}
2385	impl<
2386		T: ComplexField,
2387		Cols: Shape,
2388		LCStride: Stride,
2389		L: (for<'a> ReborrowMut<'a, Target = row::Mut<'a, T, Cols, LCStride>>),
2390	> DivAssign<f64> for row::generic::Row<L>
2391	{
2392		fn div_assign(&mut self, rhs: _) {
2393			#[track_caller]
2394			fn imp<T: ComplexField>(mut lhs: RowMut<'_, T>, rhs: &T) {
2395				lhs *= Scale(rhs.recip());
2396			}
2397			let lhs = self.rb_mut();
2398			let rhs = &from_f64::<T>(*rhs);
2399			imp(lhs.as_dyn_cols_mut().as_dyn_stride_mut(), rhs)
2400		}
2401	}
2402});
2403impl_op_assign!({
2404	impl<
2405		T: ComplexField,
2406		Cols: Shape,
2407		LCStride: Stride,
2408		L: (for<'a> ReborrowMut<'a, Target = diag::Mut<'a, T, Cols, LCStride>>),
2409	> MulAssign<f64> for diag::generic::Diag<L>
2410	{
2411		fn mul_assign(&mut self, rhs: _) {
2412			#[track_caller]
2413			fn imp<T: ComplexField>(mut lhs: ColMut<'_, T>, rhs: &T) {
2414				lhs *= Scale::from_ref(rhs);
2415			}
2416			let lhs = self.rb_mut().column_vector_mut();
2417			let rhs = &from_f64::<T>(*rhs);
2418			imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
2419		}
2420	}
2421	impl<
2422		T: ComplexField,
2423		Cols: Shape,
2424		LCStride: Stride,
2425		L: (for<'a> ReborrowMut<'a, Target = diag::Mut<'a, T, Cols, LCStride>>),
2426	> DivAssign<f64> for diag::generic::Diag<L>
2427	{
2428		fn div_assign(&mut self, rhs: _) {
2429			#[track_caller]
2430			fn imp<T: ComplexField>(mut lhs: ColMut<'_, T>, rhs: &T) {
2431				lhs *= Scale(rhs.recip());
2432			}
2433			let lhs = self.rb_mut().column_vector_mut();
2434			let rhs = &from_f64::<T>(*rhs);
2435			imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
2436		}
2437	}
2438});
2439#[cfg(feature = "sparse")]
2440mod sparse {
2441	use super::*;
2442	use crate::internal_prelude_sp::*;
2443	use csc_numeric as csc;
2444	use csr_numeric as csr;
2445	impl_binop!({
2446		impl<
2447			I: Index,
2448			T: ComplexField,
2449			Rows: Shape,
2450			Cols: Shape,
2451			RT: (Conjugate<Canonical = T>),
2452			R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Rows, Cols>>),
2453		> Mul<csr::generic::SparseRowMat<R>> for Scale<T>
2454		{
2455			type Output = SparseRowMat<I, T, Rows, Cols>;
2456
2457			fn mul(self, rhs: _) {
2458				#[track_caller]
2459				fn imp<
2460					I: Index,
2461					T: ComplexField,
2462					RT: Conjugate<Canonical = T>,
2463				>(
2464					lhs: &T,
2465					rhs: SparseRowMatRef<'_, I, RT>,
2466				) -> SparseRowMat<I, T> {
2467					(Scale::from_ref(lhs) * rhs.transpose()).into_transpose()
2468				}
2469				let lhs = &self.0;
2470				let rhs = rhs.rb();
2471				imp(lhs, rhs.as_dyn()).into_shape(rhs.nrows(), rhs.ncols())
2472			}
2473		}
2474		impl<
2475			I: Index,
2476			T: ComplexField,
2477			Rows: Shape,
2478			Cols: Shape,
2479			RT: (Conjugate<Canonical = T>),
2480			R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Rows, Cols>>),
2481		> Mul<csc::generic::SparseColMat<R>> for Scale<T>
2482		{
2483			type Output = SparseColMat<I, T, Rows, Cols>;
2484
2485			fn mul(self, rhs: _) {
2486				#[track_caller]
2487				fn imp<
2488					I: Index,
2489					T: ComplexField,
2490					RT: Conjugate<Canonical = T>,
2491				>(
2492					lhs: &T,
2493					rhs: SparseColMatRef<'_, I, RT>,
2494				) -> SparseColMat<I, T> {
2495					with_dim!(M, rhs.nrows());
2496					with_dim!(N, rhs.ncols());
2497					let rhs = rhs.as_shape(M, N);
2498					let symbolic = rhs.symbolic().to_owned().unwrap();
2499					let mut val = alloc::vec::Vec::new();
2500					val.resize(symbolic.row_idx().len(), zero());
2501					for j in rhs.ncols().indices() {
2502						for (val, rhs) in iter::zip(
2503							&mut val[symbolic.col_range(j)],
2504							rhs.val_of_col(j),
2505						) {
2506							*val = lhs * Conj::apply(rhs);
2507						}
2508					}
2509					SparseColMat::new(symbolic, val).into_shape(*M, *N)
2510				}
2511				let lhs = &self.0;
2512				let rhs = rhs.rb();
2513				imp(lhs, rhs.as_dyn()).into_shape(rhs.nrows(), rhs.ncols())
2514			}
2515		}
2516	});
2517	impl_binop!({
2518		impl<
2519			I: Index,
2520			T: ComplexField,
2521			Rows: Shape,
2522			Cols: Shape,
2523			LT: (Conjugate<Canonical = T>),
2524			L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Cols>>),
2525		> Mul<Scale<T>> for csr::generic::SparseRowMat<L>
2526		{
2527			type Output = SparseRowMat<I, T, Rows, Cols>;
2528
2529			fn mul(self, rhs: _) {
2530				#[track_caller]
2531				fn imp<
2532					I: Index,
2533					T: ComplexField,
2534					LT: Conjugate<Canonical = T>,
2535				>(
2536					rhs: &T,
2537					lhs: SparseRowMatRef<'_, I, LT>,
2538				) -> SparseRowMat<I, T> {
2539					(lhs.transpose() * Scale::from_ref(rhs)).into_transpose()
2540				}
2541				let rhs = &rhs.0;
2542				let lhs = self.rb();
2543				imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
2544			}
2545		}
2546		impl<
2547			I: Index,
2548			T: ComplexField,
2549			Rows: Shape,
2550			Cols: Shape,
2551			LT: (Conjugate<Canonical = T>),
2552			L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Cols>>),
2553		> Mul<Scale<T>> for csc::generic::SparseColMat<L>
2554		{
2555			type Output = SparseColMat<I, T, Rows, Cols>;
2556
2557			fn mul(self, rhs: _) {
2558				#[track_caller]
2559				fn imp<
2560					I: Index,
2561					T: ComplexField,
2562					LT: Conjugate<Canonical = T>,
2563				>(
2564					rhs: &T,
2565					lhs: SparseColMatRef<'_, I, LT>,
2566				) -> SparseColMat<I, T> {
2567					with_dim!(M, lhs.nrows());
2568					with_dim!(N, lhs.ncols());
2569					let lhs = lhs.as_shape(M, N);
2570					let symbolic = lhs.symbolic().to_owned().unwrap();
2571					let mut val = alloc::vec::Vec::new();
2572					val.resize(symbolic.row_idx().len(), zero());
2573					for j in lhs.ncols().indices() {
2574						for (val, lhs) in iter::zip(
2575							&mut val[symbolic.col_range(j)],
2576							lhs.val_of_col(j),
2577						) {
2578							*val = Conj::apply(lhs) * rhs;
2579						}
2580					}
2581					SparseColMat::new(symbolic, val).into_shape(*M, *N)
2582				}
2583				let rhs = &rhs.0;
2584				let lhs = self.rb();
2585				imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
2586			}
2587		}
2588		impl<
2589			I: Index,
2590			T: ComplexField,
2591			Rows: Shape,
2592			Cols: Shape,
2593			LT: (Conjugate<Canonical = T>),
2594			L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Cols>>),
2595		> Div<Scale<T>> for csr::generic::SparseRowMat<L>
2596		{
2597			type Output = SparseRowMat<I, T, Rows, Cols>;
2598
2599			fn div(self, rhs: _) {
2600				#[track_caller]
2601				fn imp<
2602					I: Index,
2603					T: ComplexField,
2604					LT: Conjugate<Canonical = T>,
2605				>(
2606					rhs: &T,
2607					lhs: SparseRowMatRef<'_, I, LT>,
2608				) -> SparseRowMat<I, T> {
2609					lhs * Scale(rhs.recip())
2610				}
2611				let rhs = &rhs.0;
2612				let lhs = self.rb();
2613				imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
2614			}
2615		}
2616		impl<
2617			I: Index,
2618			T: ComplexField,
2619			Rows: Shape,
2620			Cols: Shape,
2621			LT: (Conjugate<Canonical = T>),
2622			L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Cols>>),
2623		> Div<Scale<T>> for csc::generic::SparseColMat<L>
2624		{
2625			type Output = SparseColMat<I, T, Rows, Cols>;
2626
2627			fn div(self, rhs: _) {
2628				#[track_caller]
2629				fn imp<
2630					I: Index,
2631					T: ComplexField,
2632					LT: Conjugate<Canonical = T>,
2633				>(
2634					rhs: &T,
2635					lhs: SparseColMatRef<'_, I, LT>,
2636				) -> SparseColMat<I, T> {
2637					lhs * Scale(rhs.recip())
2638				}
2639				let rhs = &rhs.0;
2640				let lhs = self.rb();
2641				imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
2642			}
2643		}
2644	});
2645	impl_op_assign!({
2646		impl<
2647			I: Index,
2648			T: ComplexField,
2649			Rows: Shape,
2650			Cols: Shape,
2651			L: (for<'a> ReborrowMut<'a, Target = csr::Mut<'a, I, T, Rows, Cols>>),
2652		> MulAssign<Scale<T>> for csr::generic::SparseRowMat<L>
2653		{
2654			fn mul_assign(&mut self, rhs: _) {
2655				#[track_caller]
2656				fn imp<I: Index, T: ComplexField>(
2657					rhs: &T,
2658					lhs: SparseRowMatMut<'_, I, T>,
2659				) {
2660					let mut lhs = lhs.transpose_mut();
2661					lhs *= Scale::from_ref(rhs);
2662				}
2663				let rhs = &rhs.0;
2664				let lhs = self.rb_mut();
2665				imp(rhs, lhs.as_dyn_mut())
2666			}
2667		}
2668		impl<
2669			I: Index,
2670			T: ComplexField,
2671			Rows: Shape,
2672			Cols: Shape,
2673			L: (for<'a> ReborrowMut<'a, Target = csc::Mut<'a, I, T, Rows, Cols>>),
2674		> MulAssign<Scale<T>> for csc::generic::SparseColMat<L>
2675		{
2676			fn mul_assign(&mut self, rhs: _) {
2677				#[track_caller]
2678				fn imp<I: Index, T: ComplexField>(
2679					rhs: &T,
2680					lhs: SparseColMatMut<'_, I, T>,
2681				) {
2682					with_dim!(M, lhs.nrows());
2683					with_dim!(N, lhs.ncols());
2684					let mut lhs = lhs.as_shape_mut(M, N);
2685					for j in lhs.ncols().indices() {
2686						for val in lhs.rb_mut().val_of_col_mut(j) {
2687							*val *= rhs;
2688						}
2689					}
2690				}
2691				let rhs = &rhs.0;
2692				let lhs = self.rb_mut();
2693				imp(rhs, lhs.as_dyn_mut())
2694			}
2695		}
2696		impl<
2697			I: Index,
2698			T: ComplexField,
2699			Rows: Shape,
2700			Cols: Shape,
2701			L: (for<'a> ReborrowMut<'a, Target = csr::Mut<'a, I, T, Rows, Cols>>),
2702		> DivAssign<Scale<T>> for csr::generic::SparseRowMat<L>
2703		{
2704			fn div_assign(&mut self, rhs: _) {
2705				#[track_caller]
2706				fn imp<I: Index, T: ComplexField>(
2707					rhs: &T,
2708					lhs: SparseRowMatMut<'_, I, T>,
2709				) {
2710					let mut lhs = lhs.transpose_mut();
2711					lhs /= Scale::from_ref(rhs);
2712				}
2713				let rhs = &rhs.0;
2714				let lhs = self.rb_mut();
2715				imp(rhs, lhs.as_dyn_mut())
2716			}
2717		}
2718		impl<
2719			I: Index,
2720			T: ComplexField,
2721			Rows: Shape,
2722			Cols: Shape,
2723			L: (for<'a> ReborrowMut<'a, Target = csc::Mut<'a, I, T, Rows, Cols>>),
2724		> DivAssign<Scale<T>> for csc::generic::SparseColMat<L>
2725		{
2726			fn div_assign(&mut self, rhs: _) {
2727				#[track_caller]
2728				fn imp<I: Index, T: ComplexField>(
2729					rhs: &T,
2730					lhs: SparseColMatMut<'_, I, T>,
2731				) {
2732					let mut lhs = lhs.transpose_mut();
2733					lhs *= Scale(rhs.recip());
2734				}
2735				let rhs = &rhs.0;
2736				let lhs = self.rb_mut();
2737				imp(rhs, lhs.as_dyn_mut())
2738			}
2739		}
2740	});
2741	impl_binop!({
2742		impl<
2743			I: Index,
2744			T: ComplexField,
2745			Rows: Shape,
2746			Cols: Shape,
2747			RT: (Conjugate<Canonical = T>),
2748			R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Rows, Cols>>),
2749		> Mul<csr::generic::SparseRowMat<R>> for f64
2750		{
2751			type Output = SparseRowMat<I, T, Rows, Cols>;
2752
2753			fn mul(self, rhs: _) {
2754				#[track_caller]
2755				fn imp<
2756					I: Index,
2757					T: ComplexField,
2758					RT: Conjugate<Canonical = T>,
2759				>(
2760					lhs: &T,
2761					rhs: SparseRowMatRef<'_, I, RT>,
2762				) -> SparseRowMat<I, T> {
2763					(Scale::from_ref(lhs) * rhs.transpose()).into_transpose()
2764				}
2765				let lhs = &from_f64::<T>(*self);
2766				let rhs = rhs.rb();
2767				imp(lhs, rhs.as_dyn()).into_shape(rhs.nrows(), rhs.ncols())
2768			}
2769		}
2770		impl<
2771			I: Index,
2772			T: ComplexField,
2773			Rows: Shape,
2774			Cols: Shape,
2775			RT: (Conjugate<Canonical = T>),
2776			R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Rows, Cols>>),
2777		> Mul<csc::generic::SparseColMat<R>> for f64
2778		{
2779			type Output = SparseColMat<I, T, Rows, Cols>;
2780
2781			fn mul(self, rhs: _) {
2782				#[track_caller]
2783				fn imp<
2784					I: Index,
2785					T: ComplexField,
2786					RT: Conjugate<Canonical = T>,
2787				>(
2788					lhs: &T,
2789					rhs: SparseColMatRef<'_, I, RT>,
2790				) -> SparseColMat<I, T> {
2791					Scale::from_ref(lhs) * rhs
2792				}
2793				let lhs = &from_f64::<T>(*self);
2794				let rhs = rhs.rb();
2795				imp(lhs, rhs.as_dyn()).into_shape(rhs.nrows(), rhs.ncols())
2796			}
2797		}
2798	});
2799	impl_binop!({
2800		impl<
2801			I: Index,
2802			T: ComplexField,
2803			Rows: Shape,
2804			Cols: Shape,
2805			LT: (Conjugate<Canonical = T>),
2806			L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Cols>>),
2807		> Mul<f64> for csr::generic::SparseRowMat<L>
2808		{
2809			type Output = SparseRowMat<I, T, Rows, Cols>;
2810
2811			fn mul(self, rhs: _) {
2812				#[track_caller]
2813				fn imp<
2814					I: Index,
2815					T: ComplexField,
2816					LT: Conjugate<Canonical = T>,
2817				>(
2818					rhs: &T,
2819					lhs: SparseRowMatRef<'_, I, LT>,
2820				) -> SparseRowMat<I, T> {
2821					(lhs.transpose() * Scale::from_ref(rhs)).into_transpose()
2822				}
2823				let rhs = &from_f64::<T>(*rhs);
2824				let lhs = self.rb();
2825				imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
2826			}
2827		}
2828		impl<
2829			I: Index,
2830			T: ComplexField,
2831			Rows: Shape,
2832			Cols: Shape,
2833			LT: (Conjugate<Canonical = T>),
2834			L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Cols>>),
2835		> Mul<f64> for csc::generic::SparseColMat<L>
2836		{
2837			type Output = SparseColMat<I, T, Rows, Cols>;
2838
2839			fn mul(self, rhs: _) {
2840				#[track_caller]
2841				fn imp<
2842					I: Index,
2843					T: ComplexField,
2844					LT: Conjugate<Canonical = T>,
2845				>(
2846					rhs: &T,
2847					lhs: SparseColMatRef<'_, I, LT>,
2848				) -> SparseColMat<I, T> {
2849					lhs * Scale::from_ref(rhs)
2850				}
2851				let rhs = &from_f64::<T>(*rhs);
2852				let lhs = self.rb();
2853				imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
2854			}
2855		}
2856		impl<
2857			I: Index,
2858			T: ComplexField,
2859			Rows: Shape,
2860			Cols: Shape,
2861			LT: (Conjugate<Canonical = T>),
2862			L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Cols>>),
2863		> Div<f64> for csr::generic::SparseRowMat<L>
2864		{
2865			type Output = SparseRowMat<I, T, Rows, Cols>;
2866
2867			fn div(self, rhs: _) {
2868				#[track_caller]
2869				fn imp<
2870					I: Index,
2871					T: ComplexField,
2872					LT: Conjugate<Canonical = T>,
2873				>(
2874					rhs: &T,
2875					lhs: SparseRowMatRef<'_, I, LT>,
2876				) -> SparseRowMat<I, T> {
2877					lhs * Scale(rhs.recip())
2878				}
2879				let rhs = &from_f64::<T>(*rhs);
2880				let lhs = self.rb();
2881				imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
2882			}
2883		}
2884		impl<
2885			I: Index,
2886			T: ComplexField,
2887			Rows: Shape,
2888			Cols: Shape,
2889			LT: (Conjugate<Canonical = T>),
2890			L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Cols>>),
2891		> Div<f64> for csc::generic::SparseColMat<L>
2892		{
2893			type Output = SparseColMat<I, T, Rows, Cols>;
2894
2895			fn div(self, rhs: _) {
2896				#[track_caller]
2897				fn imp<
2898					I: Index,
2899					T: ComplexField,
2900					LT: Conjugate<Canonical = T>,
2901				>(
2902					rhs: &T,
2903					lhs: SparseColMatRef<'_, I, LT>,
2904				) -> SparseColMat<I, T> {
2905					lhs * Scale(rhs.recip())
2906				}
2907				let rhs = &from_f64::<T>(*rhs);
2908				let lhs = self.rb();
2909				imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
2910			}
2911		}
2912	});
2913	impl_op_assign!({
2914		impl<
2915			I: Index,
2916			T: ComplexField,
2917			Rows: Shape,
2918			Cols: Shape,
2919			L: (for<'a> ReborrowMut<'a, Target = csr::Mut<'a, I, T, Rows, Cols>>),
2920		> MulAssign<f64> for csr::generic::SparseRowMat<L>
2921		{
2922			fn mul_assign(&mut self, rhs: _) {
2923				#[track_caller]
2924				fn imp<I: Index, T: ComplexField>(
2925					rhs: &T,
2926					lhs: SparseRowMatMut<'_, I, T>,
2927				) {
2928					let mut lhs = lhs.transpose_mut();
2929					lhs *= Scale::from_ref(rhs);
2930				}
2931				let rhs = &from_f64::<T>(*rhs);
2932				let lhs = self.rb_mut();
2933				imp(rhs, lhs.as_dyn_mut())
2934			}
2935		}
2936		impl<
2937			I: Index,
2938			T: ComplexField,
2939			Rows: Shape,
2940			Cols: Shape,
2941			L: (for<'a> ReborrowMut<'a, Target = csc::Mut<'a, I, T, Rows, Cols>>),
2942		> MulAssign<f64> for csc::generic::SparseColMat<L>
2943		{
2944			fn mul_assign(&mut self, rhs: _) {
2945				#[track_caller]
2946				fn imp<I: Index, T: ComplexField>(
2947					rhs: &T,
2948					lhs: SparseColMatMut<'_, I, T>,
2949				) {
2950					*&mut { lhs } *= Scale::from_ref(rhs)
2951				}
2952				let rhs = &from_f64::<T>(*rhs);
2953				let lhs = self.rb_mut();
2954				imp(rhs, lhs.as_dyn_mut())
2955			}
2956		}
2957		impl<
2958			I: Index,
2959			T: ComplexField,
2960			Rows: Shape,
2961			Cols: Shape,
2962			L: (for<'a> ReborrowMut<'a, Target = csr::Mut<'a, I, T, Rows, Cols>>),
2963		> DivAssign<f64> for csr::generic::SparseRowMat<L>
2964		{
2965			fn div_assign(&mut self, rhs: _) {
2966				#[track_caller]
2967				fn imp<I: Index, T: ComplexField>(
2968					rhs: &T,
2969					lhs: SparseRowMatMut<'_, I, T>,
2970				) {
2971					let mut lhs = lhs.transpose_mut();
2972					lhs /= Scale::from_ref(rhs);
2973				}
2974				let rhs = &from_f64::<T>(*rhs);
2975				let lhs = self.rb_mut();
2976				imp(rhs, lhs.as_dyn_mut())
2977			}
2978		}
2979		impl<
2980			I: Index,
2981			T: ComplexField,
2982			Rows: Shape,
2983			Cols: Shape,
2984			L: (for<'a> ReborrowMut<'a, Target = csc::Mut<'a, I, T, Rows, Cols>>),
2985		> DivAssign<f64> for csc::generic::SparseColMat<L>
2986		{
2987			fn div_assign(&mut self, rhs: _) {
2988				#[track_caller]
2989				fn imp<I: Index, T: ComplexField>(
2990					rhs: &T,
2991					lhs: SparseColMatMut<'_, I, T>,
2992				) {
2993					let mut lhs = lhs.transpose_mut();
2994					lhs *= Scale(rhs.recip());
2995				}
2996				let rhs = &from_f64::<T>(*rhs);
2997				let lhs = self.rb_mut();
2998				imp(rhs, lhs.as_dyn_mut())
2999			}
3000		}
3001	});
3002	impl_op!({
3003		impl<
3004			I: Index,
3005			T: Conjugate,
3006			Rows: Shape,
3007			Cols: Shape,
3008			Inner: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, T, Rows, Cols>>),
3009		> Neg for csr::generic::SparseRowMat<Inner>
3010		{
3011			type Output = SparseRowMat<I, T::Canonical, Rows, Cols>;
3012
3013			fn neg(self) {
3014				self.rb().transpose().neg().into_transpose()
3015			}
3016		}
3017		impl<
3018			I: Index,
3019			T: Conjugate,
3020			Rows: Shape,
3021			Cols: Shape,
3022			Inner: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, T, Rows, Cols>>),
3023		> Neg for csc::generic::SparseColMat<Inner>
3024		{
3025			type Output = SparseColMat<I, T::Canonical, Rows, Cols>;
3026
3027			fn neg(self) {
3028				#[track_caller]
3029				fn imp<I: Index, T: Conjugate>(
3030					A: SparseColMatRef<'_, I, T>,
3031				) -> SparseColMat<I, T::Canonical> {
3032					with_dim!(M, A.nrows());
3033					with_dim!(N, A.ncols());
3034					let A = A.as_shape(M, N);
3035					let symbolic = A.symbolic().to_owned().unwrap();
3036					let mut val = alloc::vec::Vec::new();
3037					val.resize(symbolic.row_idx().len(), zero());
3038					for j in A.ncols().indices() {
3039						for (val, lhs) in iter::zip(
3040							&mut val[symbolic.col_range(j)],
3041							A.val_of_col(j),
3042						) {
3043							*val = -Conj::apply(lhs);
3044						}
3045					}
3046					SparseColMat::new(symbolic, val).into_shape(*M, *N)
3047				}
3048				let A = self.rb();
3049				imp(A.as_dyn()).into_shape(A.nrows(), A.ncols())
3050			}
3051		}
3052	});
3053	impl_op_assign!({
3054		impl<
3055			I: Index,
3056			T: ComplexField,
3057			Rows: Shape,
3058			Cols: Shape,
3059			RT: (Conjugate<Canonical = T>),
3060			L: (for<'a> ReborrowMut<'a, Target = csc::Mut<'a, I, T, Rows, Cols>>),
3061			R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Rows, Cols>>),
3062		> AddAssign<csc::generic::SparseColMat<R>> for csc::generic::SparseColMat<L>
3063		{
3064			fn add_assign(&mut self, rhs: _) {
3065				#[track_caller]
3066				fn imp<
3067					I: Index,
3068					T: ComplexField,
3069					RT: Conjugate<Canonical = T>,
3070				>(
3071					lhs: SparseColMatMut<'_, I, T>,
3072					rhs: SparseColMatRef<'_, I, RT>,
3073				) {
3074					crate::sparse::ops::binary_op_assign_into(
3075						lhs,
3076						rhs,
3077						add_assign_fn::<T, RT>,
3078					)
3079				}
3080				let lhs = self.rb_mut();
3081				let rhs = rhs.rb();
3082				imp(lhs.as_dyn_mut(), rhs.as_dyn())
3083			}
3084		}
3085		impl<
3086			I: Index,
3087			T: ComplexField,
3088			Rows: Shape,
3089			Cols: Shape,
3090			RT: (Conjugate<Canonical = T>),
3091			L: (for<'a> ReborrowMut<'a, Target = csc::Mut<'a, I, T, Rows, Cols>>),
3092			R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Rows, Cols>>),
3093		> SubAssign<csc::generic::SparseColMat<R>> for csc::generic::SparseColMat<L>
3094		{
3095			fn sub_assign(&mut self, rhs: _) {
3096				#[track_caller]
3097				fn imp<
3098					I: Index,
3099					T: ComplexField,
3100					RT: Conjugate<Canonical = T>,
3101				>(
3102					lhs: SparseColMatMut<'_, I, T>,
3103					rhs: SparseColMatRef<'_, I, RT>,
3104				) {
3105					crate::sparse::ops::binary_op_assign_into(
3106						lhs,
3107						rhs,
3108						sub_assign_fn::<T, RT>,
3109					)
3110				}
3111				let lhs = self.rb_mut();
3112				let rhs = rhs.rb();
3113				imp(lhs.as_dyn_mut(), rhs.as_dyn())
3114			}
3115		}
3116	});
3117	impl_op_assign!({
3118		impl<
3119			I: Index,
3120			T: ComplexField,
3121			Rows: Shape,
3122			Cols: Shape,
3123			RT: (Conjugate<Canonical = T>),
3124			L: (for<'a> ReborrowMut<'a, Target = csr::Mut<'a, I, T, Rows, Cols>>),
3125			R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Rows, Cols>>),
3126		> AddAssign<csr::generic::SparseRowMat<R>> for csr::generic::SparseRowMat<L>
3127		{
3128			fn add_assign(&mut self, rhs: _) {
3129				#[track_caller]
3130				fn imp<
3131					I: Index,
3132					T: ComplexField,
3133					RT: Conjugate<Canonical = T>,
3134				>(
3135					lhs: SparseRowMatMut<'_, I, T>,
3136					rhs: SparseRowMatRef<'_, I, RT>,
3137				) {
3138					crate::sparse::ops::binary_op_assign_into(
3139						lhs.transpose_mut(),
3140						rhs.transpose(),
3141						add_assign_fn::<T, RT>,
3142					)
3143				}
3144				let lhs = self.rb_mut();
3145				let rhs = rhs.rb();
3146				imp(lhs.as_dyn_mut(), rhs.as_dyn())
3147			}
3148		}
3149		impl<
3150			I: Index,
3151			T: ComplexField,
3152			Rows: Shape,
3153			Cols: Shape,
3154			RT: (Conjugate<Canonical = T>),
3155			L: (for<'a> ReborrowMut<'a, Target = csr::Mut<'a, I, T, Rows, Cols>>),
3156			R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Rows, Cols>>),
3157		> SubAssign<csr::generic::SparseRowMat<R>> for csr::generic::SparseRowMat<L>
3158		{
3159			fn sub_assign(&mut self, rhs: _) {
3160				#[track_caller]
3161				fn imp<
3162					I: Index,
3163					T: ComplexField,
3164					RT: Conjugate<Canonical = T>,
3165				>(
3166					lhs: SparseRowMatMut<'_, I, T>,
3167					rhs: SparseRowMatRef<'_, I, RT>,
3168				) {
3169					crate::sparse::ops::binary_op_assign_into(
3170						lhs.transpose_mut(),
3171						rhs.transpose(),
3172						sub_assign_fn::<T, RT>,
3173					)
3174				}
3175				let lhs = self.rb_mut();
3176				let rhs = rhs.rb();
3177				imp(lhs.as_dyn_mut(), rhs.as_dyn())
3178			}
3179		}
3180	});
3181	impl_binop!({
3182		impl<
3183			I: Index,
3184			T: ComplexField,
3185			Rows: Shape,
3186			Cols: Shape,
3187			LT: (Conjugate<Canonical = T>),
3188			RT: (Conjugate<Canonical = T>),
3189			L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Cols>>),
3190			R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Rows, Cols>>),
3191		> Add<csc::generic::SparseColMat<R>> for csc::generic::SparseColMat<L>
3192		{
3193			type Output = SparseColMat<I, T, Rows, Cols>;
3194
3195			fn add(self, rhs: _) {
3196				#[track_caller]
3197				fn imp<
3198					I: Index,
3199					T: ComplexField,
3200					LT: Conjugate<Canonical = T>,
3201					RT: Conjugate<Canonical = T>,
3202				>(
3203					lhs: SparseColMatRef<'_, I, LT>,
3204					rhs: SparseColMatRef<'_, I, RT>,
3205				) -> SparseColMat<I, T> {
3206					crate::sparse::ops::binary_op(lhs, rhs, add_fn::<T, LT, RT>)
3207						.unwrap()
3208				}
3209				let lhs = self.rb();
3210				let rhs = rhs.rb();
3211				let (nrows, ncols) = lhs.shape();
3212				imp(lhs.as_dyn(), rhs.as_dyn()).into_shape(nrows, ncols)
3213			}
3214		}
3215		impl<
3216			I: Index,
3217			T: ComplexField,
3218			Rows: Shape,
3219			Cols: Shape,
3220			LT: (Conjugate<Canonical = T>),
3221			RT: (Conjugate<Canonical = T>),
3222			L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Cols>>),
3223			R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Rows, Cols>>),
3224		> Sub<csc::generic::SparseColMat<R>> for csc::generic::SparseColMat<L>
3225		{
3226			type Output = SparseColMat<I, T, Rows, Cols>;
3227
3228			fn sub(self, rhs: _) {
3229				#[track_caller]
3230				fn imp<
3231					I: Index,
3232					T: ComplexField,
3233					LT: Conjugate<Canonical = T>,
3234					RT: Conjugate<Canonical = T>,
3235				>(
3236					lhs: SparseColMatRef<'_, I, LT>,
3237					rhs: SparseColMatRef<'_, I, RT>,
3238				) -> SparseColMat<I, T> {
3239					crate::sparse::ops::binary_op(lhs, rhs, sub_fn::<T, LT, RT>)
3240						.unwrap()
3241				}
3242				let lhs = self.rb();
3243				let rhs = rhs.rb();
3244				let (nrows, ncols) = lhs.shape();
3245				imp(lhs.as_dyn(), rhs.as_dyn()).into_shape(nrows, ncols)
3246			}
3247		}
3248	});
3249	impl_binop!({
3250		impl<
3251			I: Index,
3252			T: ComplexField,
3253			Rows: Shape,
3254			Cols: Shape,
3255			LT: (Conjugate<Canonical = T>),
3256			RT: (Conjugate<Canonical = T>),
3257			L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Cols>>),
3258			R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Rows, Cols>>),
3259		> Add<csr::generic::SparseRowMat<R>> for csr::generic::SparseRowMat<L>
3260		{
3261			type Output = SparseRowMat<I, T, Rows, Cols>;
3262
3263			fn add(self, rhs: _) {
3264				#[track_caller]
3265				fn imp<
3266					I: Index,
3267					T: ComplexField,
3268					LT: Conjugate<Canonical = T>,
3269					RT: Conjugate<Canonical = T>,
3270				>(
3271					lhs: SparseRowMatRef<'_, I, LT>,
3272					rhs: SparseRowMatRef<'_, I, RT>,
3273				) -> SparseRowMat<I, T> {
3274					crate::sparse::ops::binary_op(
3275						lhs.transpose(),
3276						rhs.transpose(),
3277						add_fn::<T, LT, RT>,
3278					)
3279					.unwrap()
3280					.into_transpose()
3281				}
3282				let lhs = self.rb();
3283				let rhs = rhs.rb();
3284				let (nrows, ncols) = lhs.shape();
3285				imp(lhs.as_dyn(), rhs.as_dyn()).into_shape(nrows, ncols)
3286			}
3287		}
3288		impl<
3289			I: Index,
3290			T: ComplexField,
3291			Rows: Shape,
3292			Cols: Shape,
3293			LT: (Conjugate<Canonical = T>),
3294			RT: (Conjugate<Canonical = T>),
3295			L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Cols>>),
3296			R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Rows, Cols>>),
3297		> Sub<csr::generic::SparseRowMat<R>> for csr::generic::SparseRowMat<L>
3298		{
3299			type Output = SparseRowMat<I, T, Rows, Cols>;
3300
3301			fn sub(self, rhs: _) {
3302				#[track_caller]
3303				fn imp<
3304					I: Index,
3305					T: ComplexField,
3306					LT: Conjugate<Canonical = T>,
3307					RT: Conjugate<Canonical = T>,
3308				>(
3309					lhs: SparseRowMatRef<'_, I, LT>,
3310					rhs: SparseRowMatRef<'_, I, RT>,
3311				) -> SparseRowMat<I, T> {
3312					crate::sparse::ops::binary_op(
3313						lhs.transpose(),
3314						rhs.transpose(),
3315						sub_fn::<T, LT, RT>,
3316					)
3317					.unwrap()
3318					.into_transpose()
3319				}
3320				let lhs = self.rb();
3321				let rhs = rhs.rb();
3322				let (nrows, ncols) = lhs.shape();
3323				imp(lhs.as_dyn(), rhs.as_dyn()).into_shape(nrows, ncols)
3324			}
3325		}
3326	});
3327	impl_binop!({
3328		impl<
3329			I: Index,
3330			T: ComplexField,
3331			Rows: Shape,
3332			Cols: Shape,
3333			Depth: Shape,
3334			LT: (Conjugate<Canonical = T>),
3335			RT: (Conjugate<Canonical = T>),
3336			L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Depth>>),
3337			R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Depth, Cols>>),
3338		> Mul<csc::generic::SparseColMat<R>> for csc::generic::SparseColMat<L>
3339		{
3340			type Output = SparseColMat<I, T, Rows, Cols>;
3341
3342			fn mul(self, rhs: _) {
3343				#[track_caller]
3344				fn imp<
3345					I: Index,
3346					T: ComplexField,
3347					LT: Conjugate<Canonical = T>,
3348					RT: Conjugate<Canonical = T>,
3349				>(
3350					lhs: SparseColMatRef<'_, I, LT>,
3351					rhs: SparseColMatRef<'_, I, RT>,
3352				) -> SparseColMat<I, T> {
3353					let nrows = lhs.nrows();
3354					let ncols = rhs.ncols();
3355					linalg_sp::matmul::sparse_sparse_matmul(
3356						lhs,
3357						rhs,
3358						one::<T>(),
3359						crate::Par::Seq,
3360					)
3361					.unwrap()
3362					.into_shape(nrows, ncols)
3363				}
3364				let lhs = self.rb();
3365				let rhs = rhs.rb();
3366				let nrows = lhs.nrows();
3367				let ncols = rhs.ncols();
3368				imp(lhs.as_dyn(), rhs.as_dyn()).into_shape(nrows, ncols)
3369			}
3370		}
3371		impl<
3372			I: Index,
3373			T: ComplexField,
3374			Rows: Shape,
3375			Cols: Shape,
3376			Depth: Shape,
3377			LT: (Conjugate<Canonical = T>),
3378			RT: (Conjugate<Canonical = T>),
3379			L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Depth>>),
3380			R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Depth, Cols>>),
3381		> Mul<csr::generic::SparseRowMat<R>> for csr::generic::SparseRowMat<L>
3382		{
3383			type Output = SparseRowMat<I, T, Rows, Cols>;
3384
3385			fn mul(self, rhs: _) {
3386				#[track_caller]
3387				fn imp<
3388					I: Index,
3389					T: ComplexField,
3390					LT: Conjugate<Canonical = T>,
3391					RT: Conjugate<Canonical = T>,
3392				>(
3393					lhs: SparseRowMatRef<'_, I, LT>,
3394					rhs: SparseRowMatRef<'_, I, RT>,
3395				) -> SparseRowMat<I, T> {
3396					(rhs.transpose() * lhs.transpose()).into_transpose()
3397				}
3398				let lhs = self.rb();
3399				let rhs = rhs.rb();
3400				let nrows = lhs.nrows();
3401				let ncols = rhs.ncols();
3402				imp(lhs.as_dyn(), rhs.as_dyn()).into_shape(nrows, ncols)
3403			}
3404		}
3405	});
3406	impl_binop!({
3407		impl<
3408			I: Index,
3409			T: ComplexField,
3410			Rows: Shape,
3411			Cols: Shape,
3412			Depth: Shape,
3413			LT: (Conjugate<Canonical = T>),
3414			RT: (Conjugate<Canonical = T>),
3415			RRStride: Stride,
3416			RCStride: Stride,
3417			L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Depth>>),
3418			R: (for<'a> Reborrow<
3419					'a,
3420					Target = mat::Ref<'a, RT, Depth, Cols, RRStride, RCStride>,
3421				>),
3422		> Mul<mat::generic::Mat<R>> for csc::generic::SparseColMat<L>
3423		{
3424			type Output = Mat<T, Rows, Cols>;
3425
3426			fn mul(self, rhs: _) {
3427				#[track_caller]
3428				fn imp<
3429					I: Index,
3430					T: ComplexField,
3431					LT: Conjugate<Canonical = T>,
3432					RT: Conjugate<Canonical = T>,
3433				>(
3434					lhs: SparseColMatRef<'_, I, LT>,
3435					rhs: MatRef<'_, RT>,
3436				) -> Mat<T> {
3437					let nrows = lhs.nrows();
3438					let ncols = rhs.ncols();
3439					let mut out = Mat::zeros(nrows, ncols);
3440					linalg_sp::matmul::sparse_dense_matmul(
3441						out.rb_mut(),
3442						Accum::Add,
3443						lhs,
3444						rhs,
3445						T::one_impl(),
3446						crate::Par::Seq,
3447					);
3448					out
3449				}
3450				let lhs = self.rb();
3451				let rhs = rhs.rb();
3452				let nrows = lhs.nrows();
3453				let ncols = rhs.ncols();
3454				imp(lhs.as_dyn(), rhs.as_dyn().as_dyn_stride())
3455					.into_shape(nrows, ncols)
3456			}
3457		}
3458		impl<
3459			I: Index,
3460			T: ComplexField,
3461			Rows: Shape,
3462			Cols: Shape,
3463			Depth: Shape,
3464			LT: (Conjugate<Canonical = T>),
3465			RT: (Conjugate<Canonical = T>),
3466			RRStride: Stride,
3467			RCStride: Stride,
3468			L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Depth>>),
3469			R: (for<'a> Reborrow<
3470					'a,
3471					Target = mat::Ref<'a, RT, Depth, Cols, RRStride, RCStride>,
3472				>),
3473		> Mul<mat::generic::Mat<R>> for csr::generic::SparseRowMat<L>
3474		{
3475			type Output = Mat<T, Rows, Cols>;
3476
3477			fn mul(self, rhs: _) {
3478				#[track_caller]
3479				fn imp<
3480					I: Index,
3481					T: ComplexField,
3482					LT: Conjugate<Canonical = T>,
3483					RT: Conjugate<Canonical = T>,
3484				>(
3485					lhs: SparseRowMatRef<'_, I, LT>,
3486					rhs: MatRef<'_, RT>,
3487				) -> Mat<T> {
3488					let nrows = lhs.nrows();
3489					let ncols = rhs.ncols();
3490					let mut out = Mat::zeros(nrows, ncols);
3491					linalg_sp::matmul::dense_sparse_matmul(
3492						out.rb_mut().transpose_mut(),
3493						Accum::Add,
3494						rhs.transpose(),
3495						lhs.transpose(),
3496						T::one_impl(),
3497						crate::Par::Seq,
3498					);
3499					out
3500				}
3501				let lhs = self.rb();
3502				let rhs = rhs.rb();
3503				let nrows = lhs.nrows();
3504				let ncols = rhs.ncols();
3505				imp(lhs.as_dyn(), rhs.as_dyn().as_dyn_stride())
3506					.into_shape(nrows, ncols)
3507			}
3508		}
3509	});
3510	impl_binop!({
3511		impl<
3512			I: Index,
3513			T: ComplexField,
3514			Rows: Shape,
3515			Depth: Shape,
3516			LT: (Conjugate<Canonical = T>),
3517			RT: (Conjugate<Canonical = T>),
3518			RRStride: Stride,
3519			L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Depth>>),
3520			R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Depth, RRStride>>),
3521		> Mul<col::generic::Col<R>> for csc::generic::SparseColMat<L>
3522		{
3523			type Output = Col<T, Rows>;
3524
3525			fn mul(self, rhs: _) {
3526				#[track_caller]
3527				fn imp<
3528					I: Index,
3529					T: ComplexField,
3530					LT: Conjugate<Canonical = T>,
3531					RT: Conjugate<Canonical = T>,
3532				>(
3533					lhs: SparseColMatRef<'_, I, LT>,
3534					rhs: ColRef<'_, RT>,
3535				) -> Col<T> {
3536					let nrows = lhs.nrows();
3537					let mut out = Col::zeros(nrows);
3538					linalg_sp::matmul::sparse_dense_matmul(
3539						out.rb_mut().as_mat_mut(),
3540						Accum::Add,
3541						lhs,
3542						rhs.as_mat(),
3543						T::one_impl(),
3544						crate::Par::Seq,
3545					);
3546					out
3547				}
3548				let lhs = self.rb();
3549				let rhs = rhs.rb();
3550				let nrows = lhs.nrows();
3551				imp(lhs.as_dyn(), rhs.as_dyn_rows().as_dyn_stride())
3552					.into_row_shape(nrows)
3553			}
3554		}
3555		impl<
3556			I: Index,
3557			T: ComplexField,
3558			Rows: Shape,
3559			Depth: Shape,
3560			LT: (Conjugate<Canonical = T>),
3561			RT: (Conjugate<Canonical = T>),
3562			RRStride: Stride,
3563			L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Depth>>),
3564			R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Depth, RRStride>>),
3565		> Mul<col::generic::Col<R>> for csr::generic::SparseRowMat<L>
3566		{
3567			type Output = Col<T, Rows>;
3568
3569			fn mul(self, rhs: _) {
3570				#[track_caller]
3571				fn imp<
3572					I: Index,
3573					T: ComplexField,
3574					LT: Conjugate<Canonical = T>,
3575					RT: Conjugate<Canonical = T>,
3576				>(
3577					lhs: SparseRowMatRef<'_, I, LT>,
3578					rhs: ColRef<'_, RT>,
3579				) -> Col<T> {
3580					let nrows = lhs.nrows();
3581					let mut out = Col::zeros(nrows);
3582					linalg_sp::matmul::dense_sparse_matmul(
3583						out.rb_mut().transpose_mut().as_mat_mut(),
3584						Accum::Add,
3585						rhs.transpose().as_mat(),
3586						lhs.transpose(),
3587						T::one_impl(),
3588						crate::Par::Seq,
3589					);
3590					out
3591				}
3592				let lhs = self.rb();
3593				let rhs = rhs.rb();
3594				let nrows = lhs.nrows();
3595				imp(lhs.as_dyn(), rhs.as_dyn_rows().as_dyn_stride())
3596					.into_row_shape(nrows)
3597			}
3598		}
3599	});
3600	impl_binop!({
3601		impl<
3602			I: Index,
3603			T: ComplexField,
3604			Rows: Shape,
3605			Dim: Shape,
3606			LT: (Conjugate<Canonical = T>),
3607			RT: (Conjugate<Canonical = T>),
3608			RStride: Stride,
3609			L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Dim>>),
3610			R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
3611		> Mul<diag::generic::Diag<R>> for csc::generic::SparseColMat<L>
3612		{
3613			type Output = SparseColMat<I, T, Rows, Dim>;
3614
3615			fn mul(self, rhs: _) {
3616				#[track_caller]
3617				fn imp<
3618					I: Index,
3619					T: ComplexField,
3620					LT: Conjugate<Canonical = T>,
3621					RT: Conjugate<Canonical = T>,
3622				>(
3623					lhs: SparseColMatRef<'_, I, LT>,
3624					rhs: DiagRef<'_, RT>,
3625				) -> SparseColMat<I, T> {
3626					with_dim!(M, lhs.nrows());
3627					with_dim!(N, lhs.ncols());
3628					let lhs = lhs.as_shape(M, N);
3629					let rhs = rhs.as_shape(N);
3630					let symbolic = lhs.symbolic().to_owned().unwrap();
3631					let mut out = alloc::vec::Vec::new();
3632					out.resize(symbolic.row_idx().len(), T::zero_impl());
3633					for j in lhs.ncols().indices() {
3634						let ref rhs = Conj::apply(&rhs[j]);
3635						for (out, lhs) in iter::zip(
3636							&mut out[symbolic.col_range(j)],
3637							lhs.val_of_col(j),
3638						) {
3639							*out = Conj::apply(lhs) * rhs;
3640						}
3641					}
3642					SparseColMat::new(symbolic, out).into_shape(*M, *N)
3643				}
3644				let lhs = self.rb();
3645				let rhs = rhs.rb().column_vector();
3646				let (nrows, ncols) = lhs.shape();
3647				imp(
3648					lhs.as_dyn(),
3649					rhs.as_dyn_rows().as_dyn_stride().as_diagonal(),
3650				)
3651				.into_shape(nrows, ncols)
3652			}
3653		}
3654		impl<
3655			I: Index,
3656			T: ComplexField,
3657			Rows: Shape,
3658			Dim: Shape,
3659			LT: (Conjugate<Canonical = T>),
3660			RT: (Conjugate<Canonical = T>),
3661			RStride: Stride,
3662			L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Dim>>),
3663			R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
3664		> Mul<diag::generic::Diag<R>> for csr::generic::SparseRowMat<L>
3665		{
3666			type Output = SparseRowMat<I, T, Rows, Dim>;
3667
3668			fn mul(self, rhs: _) {
3669				#[track_caller]
3670				fn imp<
3671					I: Index,
3672					T: ComplexField,
3673					LT: Conjugate<Canonical = T>,
3674					RT: Conjugate<Canonical = T>,
3675				>(
3676					lhs: SparseRowMatRef<'_, I, LT>,
3677					rhs: DiagRef<'_, RT>,
3678				) -> SparseRowMat<I, T> {
3679					with_dim!(M, lhs.nrows());
3680					with_dim!(N, lhs.ncols());
3681					let lhs = lhs.as_shape(M, N);
3682					let rhs = rhs.as_shape(N);
3683					let symbolic = lhs.symbolic().to_owned().unwrap();
3684					let mut out = alloc::vec::Vec::new();
3685					out.resize(symbolic.col_idx().len(), T::zero_impl());
3686					for i in lhs.nrows().indices() {
3687						for ((j, out), lhs) in iter::zip(
3688							iter::zip(
3689								symbolic.col_idx_of_row(i),
3690								&mut out[symbolic.row_range(i)],
3691							),
3692							lhs.val_of_row(i),
3693						) {
3694							*out = Conj::apply(lhs) * Conj::apply(&rhs[j]);
3695						}
3696					}
3697					SparseRowMat::new(symbolic, out).into_shape(*M, *N)
3698				}
3699				let lhs = self.rb();
3700				let rhs = rhs.rb().column_vector();
3701				let (nrows, ncols) = lhs.shape();
3702				imp(
3703					lhs.as_dyn(),
3704					rhs.as_dyn_rows().as_dyn_stride().as_diagonal(),
3705				)
3706				.into_shape(nrows, ncols)
3707			}
3708		}
3709	});
3710	impl_binop!({
3711		impl<
3712			I: Index,
3713			T: ComplexField,
3714			Rows: Shape,
3715			Dim: Shape,
3716			LT: (Conjugate<Canonical = T>),
3717			L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Dim>>),
3718			R: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Dim>>),
3719		> Mul<perm::generic::Perm<R>> for csc::generic::SparseColMat<L>
3720		{
3721			type Output = SparseColMat<I, T, Rows, Dim>;
3722
3723			fn mul(self, rhs: _) {
3724				#[track_caller]
3725				fn imp<
3726					I: Index,
3727					T: ComplexField,
3728					LT: Conjugate<Canonical = T>,
3729				>(
3730					lhs: SparseColMatRef<'_, I, LT>,
3731					rhs: PermRef<'_, I>,
3732				) -> SparseColMat<I, T> {
3733					with_dim!(M, lhs.nrows());
3734					with_dim!(N, lhs.ncols());
3735					let lhs = lhs.as_shape(M, N);
3736					let rhs = rhs.as_shape(N);
3737					let symbolic = lhs.symbolic();
3738					let mut out_col_ptr = alloc::vec::Vec::new();
3739					let mut out_row_idx = alloc::vec::Vec::new();
3740					let mut out = alloc::vec::Vec::new();
3741					out_col_ptr
3742						.resize(symbolic.col_ptr().len(), I::truncate(0));
3743					out_row_idx
3744						.resize(symbolic.col_ptr().len(), I::truncate(0));
3745					out.resize(
3746						symbolic.row_idx().len(),
3747						T::Canonical::zero_impl(),
3748					);
3749					let inv = rhs.bound_arrays().1;
3750					let mut pos = 0usize;
3751					for j in lhs.ncols().indices() {
3752						let inv = inv[j].zx();
3753						let row_idx = lhs.as_dyn().row_idx_of_col_raw(*inv);
3754						let len = row_idx.len();
3755						out_row_idx[pos..][..len].copy_from_slice(row_idx);
3756						for (out, lhs) in iter::zip(
3757							&mut out[pos..][..len],
3758							lhs.val_of_col(inv),
3759						) {
3760							*out = Conj::apply(lhs);
3761						}
3762						pos += row_idx.len();
3763					}
3764					out_row_idx.truncate(pos);
3765					out.truncate(pos);
3766					SparseColMat::new(
3767						unsafe {
3768							SymbolicSparseColMat::new_unchecked(
3769								symbolic.nrows(),
3770								symbolic.ncols(),
3771								out_col_ptr,
3772								None,
3773								out_row_idx,
3774							)
3775						},
3776						out,
3777					)
3778					.into_shape(*M, *N)
3779				}
3780				let lhs = self.rb();
3781				let rhs = rhs.rb();
3782				let (nrows, ncols) = lhs.shape();
3783				imp(lhs.as_dyn(), rhs.as_shape(ncols.unbound()))
3784					.into_shape(nrows, ncols)
3785			}
3786		}
3787		impl<
3788			I: Index,
3789			T: ComplexField,
3790			Rows: Shape,
3791			Dim: Shape,
3792			LT: (Conjugate<Canonical = T>),
3793			L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Dim>>),
3794			R: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Dim>>),
3795		> Mul<perm::generic::Perm<R>> for csr::generic::SparseRowMat<L>
3796		{
3797			type Output = SparseRowMat<I, T, Rows, Dim>;
3798
3799			fn mul(self, rhs: _) {
3800				#[track_caller]
3801				fn imp<
3802					I: Index,
3803					T: ComplexField,
3804					LT: Conjugate<Canonical = T>,
3805				>(
3806					lhs: SparseRowMatRef<'_, I, LT>,
3807					rhs: PermRef<'_, I>,
3808				) -> SparseRowMat<I, T> {
3809					with_dim!(M, lhs.nrows());
3810					with_dim!(N, lhs.ncols());
3811					let lhs = lhs.as_shape(M, N);
3812					let rhs = rhs.as_shape(N);
3813					let symbolic = lhs.symbolic();
3814					let mut out_row_ptr = alloc::vec::Vec::new();
3815					let mut out_col_idx = alloc::vec::Vec::new();
3816					let mut out = alloc::vec::Vec::new();
3817					out_row_ptr
3818						.resize(symbolic.row_ptr().len(), I::truncate(0));
3819					out_col_idx
3820						.resize(symbolic.row_ptr().len(), I::truncate(0));
3821					out.resize(
3822						symbolic.col_idx().len(),
3823						T::Canonical::zero_impl(),
3824					);
3825					let inv = rhs.bound_arrays().0;
3826					let mut pos = 0usize;
3827					for i in lhs.nrows().indices() {
3828						let col_idx = lhs.col_idx_of_row_raw(i);
3829						let len = col_idx.len();
3830						for ((out_j, out_v), (lhs_j, lhs_v)) in iter::zip(
3831							iter::zip(
3832								&mut out_col_idx[pos..][..len],
3833								&mut out[pos..][..len],
3834							),
3835							iter::zip(lhs.col_idx_of_row(i), lhs.val_of_row(i)),
3836						) {
3837							*out_j = *inv[lhs_j];
3838							*out_v = Conj::apply(lhs_v);
3839						}
3840						pos += col_idx.len();
3841					}
3842					out_col_idx.truncate(pos);
3843					out.truncate(pos);
3844					SparseRowMat::new(
3845						unsafe {
3846							SymbolicSparseRowMat::new_unchecked(
3847								symbolic.nrows(),
3848								symbolic.ncols(),
3849								out_row_ptr,
3850								None,
3851								out_col_idx,
3852							)
3853						},
3854						out,
3855					)
3856					.into_shape(*M, *N)
3857				}
3858				let lhs = self.rb();
3859				let rhs = rhs.rb();
3860				let (nrows, ncols) = lhs.shape();
3861				imp(lhs.as_dyn(), rhs.as_shape(ncols.unbound()))
3862					.into_shape(nrows, ncols)
3863			}
3864		}
3865	});
3866	impl_binop!({
3867		impl<
3868			I: Index,
3869			T: ComplexField,
3870			Cols: Shape,
3871			Dim: Shape,
3872			RT: (Conjugate<Canonical = T>),
3873			L: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Dim>>),
3874			R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Dim, Cols>>),
3875		> Mul<csc::generic::SparseColMat<R>> for perm::generic::Perm<L>
3876		{
3877			type Output = SparseColMat<I, T, Dim, Cols>;
3878
3879			fn mul(self, rhs: _) {
3880				(rhs.rb().transpose() * self.rb().inverse()).into_transpose()
3881			}
3882		}
3883		impl<
3884			I: Index,
3885			T: ComplexField,
3886			Cols: Shape,
3887			Dim: Shape,
3888			RT: (Conjugate<Canonical = T>),
3889			L: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Dim>>),
3890			R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Dim, Cols>>),
3891		> Mul<csr::generic::SparseRowMat<R>> for perm::generic::Perm<L>
3892		{
3893			type Output = SparseRowMat<I, T, Dim, Cols>;
3894
3895			fn mul(self, rhs: _) {
3896				(rhs.rb().transpose() * self.rb().inverse()).into_transpose()
3897			}
3898		}
3899	});
3900	impl_binop!({
3901		impl<
3902			I: Index,
3903			T: ComplexField,
3904			Cols: Shape,
3905			Dim: Shape,
3906			LT: (Conjugate<Canonical = T>),
3907			RT: (Conjugate<Canonical = T>),
3908			LStride: Stride,
3909			L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
3910			R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Dim, Cols>>),
3911		> Mul<csc::generic::SparseColMat<R>> for diag::generic::Diag<L>
3912		{
3913			type Output = SparseColMat<I, T, Dim, Cols>;
3914
3915			fn mul(self, rhs: _) {
3916				#[track_caller]
3917				fn imp<
3918					I: Index,
3919					T: ComplexField,
3920					LT: Conjugate<Canonical = T>,
3921					RT: Conjugate<Canonical = T>,
3922				>(
3923					lhs: DiagRef<'_, LT>,
3924					rhs: SparseColMatRef<'_, I, RT>,
3925				) -> SparseColMat<I, T> {
3926					(rhs.transpose() * lhs).into_transpose()
3927				}
3928				let lhs = self.rb().column_vector();
3929				let rhs = rhs.rb();
3930				let (nrows, ncols) = rhs.shape();
3931				imp(
3932					lhs.as_dyn_rows().as_dyn_stride().as_diagonal(),
3933					rhs.as_dyn(),
3934				)
3935				.into_shape(nrows, ncols)
3936			}
3937		}
3938		impl<
3939			I: Index,
3940			T: ComplexField,
3941			Cols: Shape,
3942			Dim: Shape,
3943			LT: (Conjugate<Canonical = T>),
3944			RT: (Conjugate<Canonical = T>),
3945			LStride: Stride,
3946			L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
3947			R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Dim, Cols>>),
3948		> Mul<csr::generic::SparseRowMat<R>> for diag::generic::Diag<L>
3949		{
3950			type Output = SparseRowMat<I, T, Dim, Cols>;
3951
3952			fn mul(self, rhs: _) {
3953				#[track_caller]
3954				fn imp<
3955					I: Index,
3956					T: ComplexField,
3957					LT: Conjugate<Canonical = T>,
3958					RT: Conjugate<Canonical = T>,
3959				>(
3960					lhs: DiagRef<'_, LT>,
3961					rhs: SparseRowMatRef<'_, I, RT>,
3962				) -> SparseRowMat<I, T> {
3963					(rhs.transpose() * lhs).into_transpose()
3964				}
3965				let lhs = self.rb().column_vector();
3966				let rhs = rhs.rb();
3967				let (nrows, ncols) = rhs.shape();
3968				imp(
3969					lhs.as_dyn_rows().as_dyn_stride().as_diagonal(),
3970					rhs.as_dyn(),
3971				)
3972				.into_shape(nrows, ncols)
3973			}
3974		}
3975	});
3976	impl_binop!({
3977		impl<
3978			I: Index,
3979			T: ComplexField,
3980			Rows: Shape,
3981			Cols: Shape,
3982			Depth: Shape,
3983			LT: (Conjugate<Canonical = T>),
3984			LRStride: Stride,
3985			LCStride: Stride,
3986			RT: (Conjugate<Canonical = T>),
3987			L: (for<'a> Reborrow<
3988					'a,
3989					Target = mat::Ref<'a, LT, Rows, Depth, LRStride, LCStride>,
3990				>),
3991			R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Depth, Cols>>),
3992		> Mul<csc::generic::SparseColMat<R>> for mat::generic::Mat<L>
3993		{
3994			type Output = Mat<T, Rows, Cols>;
3995
3996			fn mul(self, rhs: _) {
3997				#[track_caller]
3998				fn imp<
3999					I: Index,
4000					T: ComplexField,
4001					LT: Conjugate<Canonical = T>,
4002					RT: Conjugate<Canonical = T>,
4003				>(
4004					lhs: MatRef<'_, LT>,
4005					rhs: SparseColMatRef<'_, I, RT>,
4006				) -> Mat<T> {
4007					let nrows = lhs.nrows();
4008					let ncols = rhs.ncols();
4009					let mut out = Mat::zeros(nrows, ncols);
4010					linalg_sp::matmul::dense_sparse_matmul(
4011						out.rb_mut(),
4012						Accum::Add,
4013						lhs,
4014						rhs,
4015						T::one_impl(),
4016						crate::Par::Seq,
4017					);
4018					out
4019				}
4020				let lhs = self.rb();
4021				let rhs = rhs.rb();
4022				let nrows = lhs.nrows();
4023				let ncols = rhs.ncols();
4024				imp(lhs.as_dyn().as_dyn_stride(), rhs.as_dyn())
4025					.into_shape(nrows, ncols)
4026			}
4027		}
4028		impl<
4029			I: Index,
4030			T: ComplexField,
4031			Rows: Shape,
4032			Cols: Shape,
4033			Depth: Shape,
4034			LT: (Conjugate<Canonical = T>),
4035			LRStride: Stride,
4036			LCStride: Stride,
4037			RT: (Conjugate<Canonical = T>),
4038			L: (for<'a> Reborrow<
4039					'a,
4040					Target = mat::Ref<'a, LT, Rows, Depth, LRStride, LCStride>,
4041				>),
4042			R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Depth, Cols>>),
4043		> Mul<csr::generic::SparseRowMat<R>> for mat::generic::Mat<L>
4044		{
4045			type Output = Mat<T, Rows, Cols>;
4046
4047			fn mul(self, rhs: _) {
4048				#[track_caller]
4049				fn imp<
4050					I: Index,
4051					T: ComplexField,
4052					LT: Conjugate<Canonical = T>,
4053					RT: Conjugate<Canonical = T>,
4054				>(
4055					lhs: MatRef<'_, LT>,
4056					rhs: SparseRowMatRef<'_, I, RT>,
4057				) -> Mat<T> {
4058					let nrows = lhs.nrows();
4059					let ncols = rhs.ncols();
4060					let mut out = Mat::zeros(nrows, ncols);
4061					linalg_sp::matmul::sparse_dense_matmul(
4062						out.rb_mut().transpose_mut(),
4063						Accum::Add,
4064						rhs.transpose(),
4065						lhs.transpose(),
4066						T::one_impl(),
4067						crate::Par::Seq,
4068					);
4069					out
4070				}
4071				let lhs = self.rb();
4072				let rhs = rhs.rb();
4073				let nrows = lhs.nrows();
4074				let ncols = rhs.ncols();
4075				imp(lhs.as_dyn().as_dyn_stride(), rhs.as_dyn())
4076					.into_shape(nrows, ncols)
4077			}
4078		}
4079	});
4080	impl_binop!({
4081		impl<
4082			I: Index,
4083			T: ComplexField,
4084			Cols: Shape,
4085			Depth: Shape,
4086			LT: (Conjugate<Canonical = T>),
4087			LCStride: Stride,
4088			RT: (Conjugate<Canonical = T>),
4089			L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Depth, LCStride>>),
4090			R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Depth, Cols>>),
4091		> Mul<csc::generic::SparseColMat<R>> for row::generic::Row<L>
4092		{
4093			type Output = Row<T, Cols>;
4094
4095			fn mul(self, rhs: _) {
4096				#[track_caller]
4097				fn imp<
4098					I: Index,
4099					T: ComplexField,
4100					LT: Conjugate<Canonical = T>,
4101					RT: Conjugate<Canonical = T>,
4102				>(
4103					lhs: RowRef<'_, LT>,
4104					rhs: SparseColMatRef<'_, I, RT>,
4105				) -> Row<T> {
4106					let ncols = rhs.ncols();
4107					let mut out = Row::zeros(ncols);
4108					linalg_sp::matmul::dense_sparse_matmul(
4109						out.rb_mut().as_mat_mut(),
4110						Accum::Add,
4111						lhs.as_mat(),
4112						rhs,
4113						T::one_impl(),
4114						crate::Par::Seq,
4115					);
4116					out
4117				}
4118				let lhs = self.rb();
4119				let rhs = rhs.rb();
4120				let ncols = rhs.ncols();
4121				imp(lhs.as_dyn_cols().as_dyn_stride(), rhs.as_dyn())
4122					.into_col_shape(ncols)
4123			}
4124		}
4125		impl<
4126			I: Index,
4127			T: ComplexField,
4128			Cols: Shape,
4129			Depth: Shape,
4130			LT: (Conjugate<Canonical = T>),
4131			LCStride: Stride,
4132			RT: (Conjugate<Canonical = T>),
4133			L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Depth, LCStride>>),
4134			R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Depth, Cols>>),
4135		> Mul<csr::generic::SparseRowMat<R>> for row::generic::Row<L>
4136		{
4137			type Output = Row<T, Cols>;
4138
4139			fn mul(self, rhs: _) {
4140				#[track_caller]
4141				fn imp<
4142					I: Index,
4143					T: ComplexField,
4144					LT: Conjugate<Canonical = T>,
4145					RT: Conjugate<Canonical = T>,
4146				>(
4147					lhs: RowRef<'_, LT>,
4148					rhs: SparseRowMatRef<'_, I, RT>,
4149				) -> Row<T> {
4150					let ncols = rhs.ncols();
4151					let mut out = Row::zeros(ncols);
4152					linalg_sp::matmul::sparse_dense_matmul(
4153						out.rb_mut().transpose_mut().as_mat_mut(),
4154						Accum::Add,
4155						rhs.transpose(),
4156						lhs.transpose().as_mat(),
4157						T::one_impl(),
4158						crate::Par::Seq,
4159					);
4160					out
4161				}
4162				let lhs = self.rb();
4163				let rhs = rhs.rb();
4164				let ncols = rhs.ncols();
4165				imp(lhs.as_dyn_cols().as_dyn_stride(), rhs.as_dyn())
4166					.into_col_shape(ncols)
4167			}
4168		}
4169	});
4170	fn add_fn<
4171		T: ComplexField,
4172		LhsT: Conjugate<Canonical = T>,
4173		RhsT: Conjugate<Canonical = T>,
4174	>(
4175		lhs: Option<&LhsT>,
4176		rhs: Option<&RhsT>,
4177	) -> T {
4178		lhs.map(Conj::apply).unwrap_or_else(zero::<T>)
4179			+ rhs.map(Conj::apply).unwrap_or_else(zero::<T>)
4180	}
4181	fn sub_fn<
4182		T: ComplexField,
4183		LhsT: Conjugate<Canonical = T>,
4184		RhsT: Conjugate<Canonical = T>,
4185	>(
4186		lhs: Option<&LhsT>,
4187		rhs: Option<&RhsT>,
4188	) -> T {
4189		lhs.map(Conj::apply).unwrap_or_else(zero::<T>)
4190			- rhs.map(Conj::apply).unwrap_or_else(zero::<T>)
4191	}
4192	fn add_assign_fn<T: ComplexField, RhsT: Conjugate<Canonical = T>>(
4193		dst: &mut T,
4194		rhs: Option<&RhsT>,
4195	) {
4196		if let Some(rhs) = rhs {
4197			*dst += Conj::apply(rhs);
4198		}
4199	}
4200	fn sub_assign_fn<T: ComplexField, RhsT: Conjugate<Canonical = T>>(
4201		dst: &mut T,
4202		rhs: Option<&RhsT>,
4203	) {
4204		if let Some(rhs) = rhs {
4205			*dst -= Conj::apply(rhs);
4206		}
4207	}
4208}
4209#[cfg(test)]
4210#[allow(non_snake_case)]
4211mod test {
4212	use crate::assert;
4213	use crate::col::*;
4214	use crate::internal_prelude::*;
4215	use crate::mat::*;
4216	use crate::perm::*;
4217	use crate::row::*;
4218	use assert_approx_eq::assert_approx_eq;
4219	fn matrices() -> (Mat<f64>, Mat<f64>) {
4220		let A = mat![[2.8, -3.3], [-1.7, 5.2], [4.6, -8.3],];
4221		let B = mat![[-7.9, 8.3], [4.7, -3.2], [3.8, -5.2],];
4222		(A, B)
4223	}
4224	fn rows() -> (Row<f64>, Row<f64>) {
4225		(row![2.8, -3.3], row![-7.9, 8.3])
4226	}
4227	fn cols() -> (Col<f64>, Col<f64>) {
4228		(col![2.8, -3.3], col![-7.9, 8.3])
4229	}
4230	#[test]
4231	#[should_panic]
4232	fn test_adding_matrices_of_different_sizes_should_panic() {
4233		let A = mat![[1.0, 2.0], [3.0, 4.0]];
4234		let B = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]];
4235		_ = A + B;
4236	}
4237	#[test]
4238	#[should_panic]
4239	fn test_subtracting_two_matrices_of_different_sizes_should_panic() {
4240		let A = mat![[1.0, 2.0], [3.0, 4.0]];
4241		let B = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]];
4242		_ = A - B;
4243	}
4244	#[test]
4245	fn test_matrix_add() {
4246		let (A, B) = matrices();
4247		let expected = mat![[-5.1, 5.0], [3.0, 2.0], [8.4, -13.5],];
4248		assert_matrix_approx_eq(A.as_ref() + B.as_ref(), &expected);
4249		assert_matrix_approx_eq(&A + &B, &expected);
4250		assert_matrix_approx_eq(A.as_ref() + &B, &expected);
4251		assert_matrix_approx_eq(&A + B.as_ref(), &expected);
4252		assert_matrix_approx_eq(A.as_ref() + B.clone(), &expected);
4253		assert_matrix_approx_eq(&A + B.clone(), &expected);
4254		assert_matrix_approx_eq(A.clone() + B.as_ref(), &expected);
4255		assert_matrix_approx_eq(A.clone() + &B, &expected);
4256		assert_matrix_approx_eq(A + B, &expected);
4257	}
4258	#[test]
4259	fn test_row_add() {
4260		let (A, B) = rows();
4261		let expected = row![-5.1, 5.0];
4262		assert_row_approx_eq(A.as_ref() + B.as_ref(), &expected);
4263		assert_row_approx_eq(&A + &B, &expected);
4264		assert_row_approx_eq(A.as_ref() + &B, &expected);
4265		assert_row_approx_eq(&A + B.as_ref(), &expected);
4266		assert_row_approx_eq(A.as_ref() + B.clone(), &expected);
4267		assert_row_approx_eq(A.clone() + B.as_ref(), &expected);
4268		assert_row_approx_eq(&A + B.clone(), &expected);
4269		assert_row_approx_eq(A.clone() + &B, &expected);
4270		assert_row_approx_eq(A + B, &expected);
4271	}
4272	#[test]
4273	fn test_col_add() {
4274		let (A, B) = cols();
4275		let expected = col![-5.1, 5.0];
4276		assert_col_approx_eq(A.as_ref() + B.as_ref(), &expected);
4277		assert_col_approx_eq(&A + &B, &expected);
4278		assert_col_approx_eq(A.as_ref() + &B, &expected);
4279		assert_col_approx_eq(&A + B.as_ref(), &expected);
4280		assert_col_approx_eq(A.as_ref() + B.clone(), &expected);
4281		assert_col_approx_eq(A.clone() + B.as_ref(), &expected);
4282		assert_col_approx_eq(&A + B.clone(), &expected);
4283		assert_col_approx_eq(A.clone() + &B, &expected);
4284		assert_col_approx_eq(A + B, &expected);
4285	}
4286	#[test]
4287	fn test_matrix_sub() {
4288		let (A, B) = matrices();
4289		let expected = mat![[10.7, -11.6], [-6.4, 8.4], [0.8, -3.1],];
4290		assert_matrix_approx_eq(A.as_ref() - B.as_ref(), &expected);
4291		assert_matrix_approx_eq(&A - &B, &expected);
4292		assert_matrix_approx_eq(A.as_ref() - &B, &expected);
4293		assert_matrix_approx_eq(&A - B.as_ref(), &expected);
4294		assert_matrix_approx_eq(A.as_ref() - B.clone(), &expected);
4295		assert_matrix_approx_eq(&A - B.clone(), &expected);
4296		assert_matrix_approx_eq(A.clone() - B.as_ref(), &expected);
4297		assert_matrix_approx_eq(A.clone() - &B, &expected);
4298		assert_matrix_approx_eq(A - B, &expected);
4299	}
4300	#[test]
4301	fn test_row_sub() {
4302		let (A, B) = rows();
4303		let expected = row![10.7, -11.6];
4304		assert_row_approx_eq(A.as_ref() - B.as_ref(), &expected);
4305		assert_row_approx_eq(&A - &B, &expected);
4306		assert_row_approx_eq(A.as_ref() - &B, &expected);
4307		assert_row_approx_eq(&A - B.as_ref(), &expected);
4308		assert_row_approx_eq(A.as_ref() - B.clone(), &expected);
4309		assert_row_approx_eq(A.clone() - B.as_ref(), &expected);
4310		assert_row_approx_eq(&A - B.clone(), &expected);
4311		assert_row_approx_eq(A.clone() - &B, &expected);
4312		assert_row_approx_eq(A - B, &expected);
4313	}
4314	#[test]
4315	fn test_col_sub() {
4316		let (A, B) = cols();
4317		let expected = col![10.7, -11.6];
4318		assert_col_approx_eq(A.as_ref() - B.as_ref(), &expected);
4319		assert_col_approx_eq(&A - &B, &expected);
4320		assert_col_approx_eq(A.as_ref() - &B, &expected);
4321		assert_col_approx_eq(&A - B.as_ref(), &expected);
4322		assert_col_approx_eq(A.as_ref() - B.clone(), &expected);
4323		assert_col_approx_eq(A.clone() - B.as_ref(), &expected);
4324		assert_col_approx_eq(&A - B.clone(), &expected);
4325		assert_col_approx_eq(A.clone() - &B, &expected);
4326		assert_col_approx_eq(A - B, &expected);
4327	}
4328	#[test]
4329	fn test_neg() {
4330		let (A, _) = matrices();
4331		let expected = mat![[-2.8, 3.3], [1.7, -5.2], [-4.6, 8.3],];
4332		assert!(-A == expected);
4333	}
4334	#[test]
4335	fn test_scalar_mul() {
4336		use crate::Scale as scale;
4337		let (A, _) = matrices();
4338		let k = 3.0;
4339		let expected =
4340			Mat::from_fn(A.nrows(), A.ncols(), |i, j| A.as_ref()[(i, j)] * k);
4341		{
4342			assert_matrix_approx_eq(A.as_ref() * scale(k), &expected);
4343			assert_matrix_approx_eq(&A * scale(k), &expected);
4344			assert_matrix_approx_eq(A.as_ref() * scale(k), &expected);
4345			assert_matrix_approx_eq(&A * scale(k), &expected);
4346			assert_matrix_approx_eq(A.as_ref() * scale(k), &expected);
4347			assert_matrix_approx_eq(&A * scale(k), &expected);
4348			assert_matrix_approx_eq(A.clone() * scale(k), &expected);
4349			assert_matrix_approx_eq(A.clone() * scale(k), &expected);
4350			assert_matrix_approx_eq(A * scale(k), &expected);
4351		}
4352		let (A, _) = matrices();
4353		{
4354			assert_matrix_approx_eq(scale(k) * A.as_ref(), &expected);
4355			assert_matrix_approx_eq(scale(k) * &A, &expected);
4356			assert_matrix_approx_eq(scale(k) * A.as_ref(), &expected);
4357			assert_matrix_approx_eq(scale(k) * &A, &expected);
4358			assert_matrix_approx_eq(scale(k) * A.as_ref(), &expected);
4359			assert_matrix_approx_eq(scale(k) * &A, &expected);
4360			assert_matrix_approx_eq(scale(k) * A.clone(), &expected);
4361			assert_matrix_approx_eq(scale(k) * A.clone(), &expected);
4362			assert_matrix_approx_eq(scale(k) * A, &expected);
4363		}
4364	}
4365	#[test]
4366	fn test_diag_mul() {
4367		let (A, _) = matrices();
4368		let diag_left = mat![[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 3.0]];
4369		let diag_right = mat![[4.0, 0.0], [0.0, 5.0]];
4370		assert!(&diag_left * &A == diag_left.as_ref().diagonal() * &A);
4371		assert!(&A * &diag_right == &A * diag_right.as_ref().diagonal());
4372	}
4373	#[test]
4374	fn test_perm_mul() {
4375		let A = Mat::from_fn(6, 5, |i, j| (j + 5 * i) as f64);
4376		let pl = Perm::<usize>::new_checked(
4377			Box::new([5, 1, 4, 0, 2, 3]),
4378			Box::new([3, 1, 4, 5, 2, 0]),
4379			6,
4380		);
4381		let pr = Perm::<usize>::new_checked(
4382			Box::new([1, 4, 0, 2, 3]),
4383			Box::new([2, 0, 3, 4, 1]),
4384			5,
4385		);
4386		let perm_left = mat![
4387			[0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
4388			[0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
4389			[0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
4390			[1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
4391			[0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
4392			[0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
4393		];
4394		let perm_right = mat![
4395			[0.0, 1.0, 0.0, 0.0, 0.0],
4396			[0.0, 0.0, 0.0, 0.0, 1.0],
4397			[1.0, 0.0, 0.0, 0.0, 0.0],
4398			[0.0, 0.0, 1.0, 0.0, 0.0],
4399			[0.0, 0.0, 0.0, 1.0, 0.0],
4400		];
4401		assert!(
4402			&pl * pl.as_ref().inverse()
4403				== PermRef::<'_, usize>::new_checked(
4404					&[0, 1, 2, 3, 4, 5],
4405					&[0, 1, 2, 3, 4, 5],
4406					6
4407				)
4408		);
4409		assert!(&perm_left * &A == &pl * &A);
4410		assert!(&A * &perm_right == &A * &pr);
4411	}
4412	#[test]
4413	fn test_matmul_col_row() {
4414		let A = Col::from_fn(6, |i| i as f64);
4415		let B = Row::from_fn(6, |j| (5 * j + 1) as f64);
4416		assert!(&A * &B == A.as_mat() * B.as_mat());
4417		assert!(&B * &A == (B.as_mat() * A.as_mat())[(0, 0)],);
4418	}
4419	fn assert_row_approx_eq(given: Row<f64>, expected: &Row<f64>) {
4420		assert_eq!(given.nrows(), expected.nrows());
4421		for i in 0..given.nrows() {
4422			assert_approx_eq!(given.as_ref()[i], expected.as_ref()[i]);
4423		}
4424	}
4425	fn assert_col_approx_eq(given: Col<f64>, expected: &Col<f64>) {
4426		assert_eq!(given.ncols(), expected.ncols());
4427		for i in 0..given.ncols() {
4428			assert_approx_eq!(given.as_ref()[i], expected.as_ref()[i]);
4429		}
4430	}
4431	fn assert_matrix_approx_eq(given: Mat<f64>, expected: &Mat<f64>) {
4432		assert_eq!(given.nrows(), expected.nrows());
4433		assert_eq!(given.ncols(), expected.ncols());
4434		for i in 0..given.nrows() {
4435			for j in 0..given.ncols() {
4436				assert_approx_eq!(
4437					given.as_ref()[(i, j)],
4438					expected.as_ref()[(i, j)]
4439				);
4440			}
4441		}
4442	}
4443}