faer/linalg/
mat_ops.rs

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