1
1
#region copyright
2
+
2
3
/*
3
4
* MIT License
4
5
*
22
23
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
24
* SOFTWARE.
24
25
*/
26
+
25
27
#endregion
26
28
27
29
@@ -40,6 +42,7 @@ public sealed partial class GenTensor<T, TWrapper>
40
42
: ICloneable where TWrapper : struct , IOperations < T >
41
43
{
42
44
#region Composition
45
+
43
46
/// <summary>
44
47
/// Creates a new axis that is put backward
45
48
/// and then sets all elements as children
@@ -67,6 +70,7 @@ public static GenTensor<T, TWrapper> Concat(GenTensor<T, TWrapper> a, GenTensor<
67
70
#endregion
68
71
69
72
#region Constructors
73
+
70
74
/// <summary>
71
75
/// Creates a tensor whose all matrices are identity matrices
72
76
/// <para>1 is achieved with <see cref="IOperations{T}.CreateOne"/></para>
@@ -145,36 +149,31 @@ public static GenTensor<T, TWrapper> CreateMatrix(int width, int height)
145
149
/// (its only argument is an array of integers which are indices of the tensor)
146
150
/// </summary>
147
151
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
148
- public static GenTensor < T , TWrapper > CreateTensor ( TensorShape shape , Func < int [ ] , T > operation , Threading threading = Threading . Single )
149
- => Constructors < T , TWrapper > . CreateTensor ( shape , operation , threading ) ;
152
+ public static GenTensor < T , TWrapper > CreateTensor ( TensorShape shape , Func < int [ ] , T > operation , Threading threading = Threading . Single ) => Constructors < T , TWrapper > . CreateTensor ( shape , operation , threading ) ;
150
153
151
154
/// <summary>
152
155
/// Creates a tensor from an array
153
156
/// </summary>
154
157
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
155
- public static GenTensor < T , TWrapper > CreateTensor ( T [ ] data )
156
- => Constructors < T , TWrapper > . CreateTensor ( data ) ;
158
+ public static GenTensor < T , TWrapper > CreateTensor ( T [ ] data ) => Constructors < T , TWrapper > . CreateTensor ( data ) ;
157
159
158
160
/// <summary>
159
161
/// Creates a tensor from a two-dimensional array
160
162
/// </summary>
161
163
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
162
- public static GenTensor < T , TWrapper > CreateTensor ( T [ , ] data )
163
- => Constructors < T , TWrapper > . CreateTensor ( data ) ;
164
+ public static GenTensor < T , TWrapper > CreateTensor ( T [ , ] data ) => Constructors < T , TWrapper > . CreateTensor ( data ) ;
164
165
165
166
/// <summary>
166
167
/// Creates a tensor from a three-dimensional array
167
168
/// </summary>
168
169
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
169
- public static GenTensor < T , TWrapper > CreateTensor ( T [ , , ] data )
170
- => Constructors < T , TWrapper > . CreateTensor ( data ) ;
170
+ public static GenTensor < T , TWrapper > CreateTensor ( T [ , , ] data ) => Constructors < T , TWrapper > . CreateTensor ( data ) ;
171
171
172
172
/// <summary>
173
173
/// Creates a tensor from an n-dimensional array
174
174
/// </summary>
175
175
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
176
- public static GenTensor < T , TWrapper > CreateTensor ( Array data )
177
- => Constructors < T , TWrapper > . CreateTensor ( data ) ;
176
+ public static GenTensor < T , TWrapper > CreateTensor ( Array data ) => Constructors < T , TWrapper > . CreateTensor ( data ) ;
178
177
179
178
#endregion
180
179
@@ -186,6 +185,42 @@ public static GenTensor<T, TWrapper> CreateTensor(Array data)
186
185
/// </summary>
187
186
public GenTensor < T , TWrapper > RowEchelonFormSimple ( )
188
187
=> EchelonForm < T , TWrapper > . RowEchelonFormSimple ( this ) ;
188
+
189
+ /// <summary>
190
+ /// Decomposes a matrix into a triangular one.
191
+ /// Is of the Row Echelon Form (leading elements might be differ from ones).
192
+ ///
193
+ /// In addition, returns a permutation that algorithm performs with rows.
194
+ /// Permutation array is size of rows there are in matrix.
195
+ ///
196
+ /// Initial state of that array is:
197
+ /// 1 2 3 ... numberOfRows
198
+ ///
199
+ /// For example, algorithm swaps first and third rows then:
200
+ /// 3 2 1 ... numberOfRows
201
+ ///
202
+ /// It can be useful performing decompositions
203
+ /// </summary>
204
+ public ( GenTensor < T , TWrapper > , int [ ] ) RowEchelonFormPermuteSimple ( )
205
+ => EchelonForm < T , TWrapper > . RowEchelonFormPermuteSimple ( this ) ;
206
+
207
+ /// <summary>
208
+ /// Decomposes a matrix into a triangular one.
209
+ /// Is of the Row Echelon Form (leading elements might be differ from ones).
210
+ ///
211
+ /// In addition, returns a permutation that algorithm performs with rows.
212
+ /// Permutation array is size of rows there are in matrix.
213
+ ///
214
+ /// Initial state of that array is:
215
+ /// 1 2 3 ... numberOfRows
216
+ ///
217
+ /// For example, algorithm swaps first and third rows then:
218
+ /// 3 2 1 ... numberOfRows
219
+ ///
220
+ /// It can be useful performing decompositions
221
+ /// </summary>
222
+ public ( GenTensor < T , TWrapper > , int [ ] ) RowEchelonFormPermuteSafeDivision ( )
223
+ => EchelonForm < T , TWrapper > . RowEchelonFormPermuteSafeDivision ( this ) ;
189
224
190
225
/// <summary>
191
226
/// Decomposes a matrix into a triangular one.
@@ -196,7 +231,6 @@ public GenTensor<T, TWrapper> RowEchelonFormSafeDivision()
196
231
=> EchelonForm < T , TWrapper > . RowEchelonFormSafeDivision ( this ) ;
197
232
198
233
199
-
200
234
/// <summary>
201
235
/// Decomposes a matrix into a triangular one.
202
236
/// Is of the Row Echelon Form (leading elements are ones).
@@ -215,7 +249,6 @@ public GenTensor<T, TWrapper> RowEchelonFormLeadingOnesSafeDivision()
215
249
=> EchelonForm < T , TWrapper > . RowEchelonFormLeadingOnesSafeDivision ( this ) ;
216
250
217
251
218
-
219
252
/// <summary>
220
253
/// Finds the reduced echelon form of a matrix.
221
254
/// </summary>
@@ -228,6 +261,16 @@ public GenTensor<T, TWrapper> ReducedRowEchelonFormSimple()
228
261
/// </summary>
229
262
public GenTensor < T , TWrapper > ReducedRowEchelonFormSafeDivision ( )
230
263
=> EchelonForm < T , TWrapper > . ReducedRowEchelonFormSafeDivision ( this ) ;
264
+
265
+ /// <summary>
266
+ /// Finds the reduced echelon form of a matrix.
267
+ /// Uses safe division, i. e. perform division only when computing the final result.
268
+ ///
269
+ /// Additionally returns row permutation
270
+ /// </summary>
271
+ public ( GenTensor < T , TWrapper > , int [ ] ) ReducedRowEchelonFormPermuteSafeDivision ( )
272
+ => EchelonForm < T , TWrapper > . ReducedRowEchelonFormPermuteSafeDivision ( this ) ;
273
+
231
274
#endregion
232
275
233
276
#region Determinant
@@ -307,6 +350,7 @@ public void InvertMatrix()
307
350
/// </summary>
308
351
public void TensorMatrixInvert ( )
309
352
=> Inversion < T , TWrapper > . TensorMatrixInvert ( this ) ;
353
+
310
354
#endregion
311
355
312
356
#region Elementary matrix operations
@@ -398,70 +442,80 @@ public static GenTensor<T, TWrapper> TensorMatrixMultiply(GenTensor<T, TWrapper>
398
442
/// T1 + T2
399
443
/// </summary>
400
444
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
401
- public static GenTensor < T , TWrapper > PiecewiseAdd ( GenTensor < T , TWrapper > a , GenTensor < T , TWrapper > b , Threading threading = Threading . Single )
445
+ public static GenTensor < T , TWrapper > PiecewiseAdd ( GenTensor < T , TWrapper > a , GenTensor < T , TWrapper > b ,
446
+ Threading threading = Threading . Single )
402
447
=> PiecewiseArithmetics < T , TWrapper > . PiecewiseAdd ( a , b , threading ) ;
403
448
404
449
/// <summary>
405
450
/// T1 - T2
406
451
/// </summary>
407
452
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
408
- public static GenTensor < T , TWrapper > PiecewiseSubtract ( GenTensor < T , TWrapper > a , GenTensor < T , TWrapper > b , Threading threading = Threading . Single )
453
+ public static GenTensor < T , TWrapper > PiecewiseSubtract ( GenTensor < T , TWrapper > a , GenTensor < T , TWrapper > b ,
454
+ Threading threading = Threading . Single )
409
455
=> PiecewiseArithmetics < T , TWrapper > . PiecewiseSubtract ( a , b , threading ) ;
410
456
411
457
/// <summary>
412
458
/// T1 * T2
413
459
/// </summary>
414
460
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
415
- public static GenTensor < T , TWrapper > PiecewiseMultiply ( GenTensor < T , TWrapper > a , GenTensor < T , TWrapper > b , Threading threading = Threading . Single )
461
+ public static GenTensor < T , TWrapper > PiecewiseMultiply ( GenTensor < T , TWrapper > a , GenTensor < T , TWrapper > b ,
462
+ Threading threading = Threading . Single )
416
463
=> PiecewiseArithmetics < T , TWrapper > . PiecewiseMultiply ( a , b , threading ) ;
417
464
418
465
/// <summary>
419
466
/// T1 / T2
420
467
/// </summary>
421
468
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
422
- public static GenTensor < T , TWrapper > PiecewiseDivide ( GenTensor < T , TWrapper > a , GenTensor < T , TWrapper > b , Threading threading = Threading . Single )
469
+ public static GenTensor < T , TWrapper > PiecewiseDivide ( GenTensor < T , TWrapper > a , GenTensor < T , TWrapper > b ,
470
+ Threading threading = Threading . Single )
423
471
=> PiecewiseArithmetics < T , TWrapper > . PiecewiseDivide ( a , b , threading ) ;
424
472
425
473
/// <summary>
426
474
/// T1 + const
427
475
/// </summary>
428
476
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
429
- public static GenTensor < T , TWrapper > PiecewiseAdd ( GenTensor < T , TWrapper > a , T b , Threading threading = Threading . Single )
477
+ public static GenTensor < T , TWrapper > PiecewiseAdd ( GenTensor < T , TWrapper > a , T b ,
478
+ Threading threading = Threading . Single )
430
479
=> PiecewiseArithmetics < T , TWrapper > . PiecewiseAdd ( a , b , threading ) ;
431
480
432
481
/// <summary>
433
482
/// T1 - const
434
483
/// </summary>
435
484
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
436
- public static GenTensor < T , TWrapper > PiecewiseSubtract ( GenTensor < T , TWrapper > a , T b , Threading threading = Threading . Single )
485
+ public static GenTensor < T , TWrapper > PiecewiseSubtract ( GenTensor < T , TWrapper > a , T b ,
486
+ Threading threading = Threading . Single )
437
487
=> PiecewiseArithmetics < T , TWrapper > . PiecewiseSubtract ( a , b , threading ) ;
438
488
439
489
/// <summary>
440
490
/// const - T1
441
491
/// </summary>
442
492
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
443
- public static GenTensor < T , TWrapper > PiecewiseSubtract ( T a , GenTensor < T , TWrapper > b , Threading threading = Threading . Single )
493
+ public static GenTensor < T , TWrapper > PiecewiseSubtract ( T a , GenTensor < T , TWrapper > b ,
494
+ Threading threading = Threading . Single )
444
495
=> PiecewiseArithmetics < T , TWrapper > . PiecewiseSubtract ( a , b , threading ) ;
445
496
446
497
/// <summary>
447
498
/// T1 * const
448
499
/// </summary>
449
500
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
450
- public static GenTensor < T , TWrapper > PiecewiseMultiply ( GenTensor < T , TWrapper > a , T b , Threading threading = Threading . Single )
501
+ public static GenTensor < T , TWrapper > PiecewiseMultiply ( GenTensor < T , TWrapper > a , T b ,
502
+ Threading threading = Threading . Single )
451
503
=> PiecewiseArithmetics < T , TWrapper > . PiecewiseMultiply ( a , b , threading ) ;
452
504
453
505
/// <summary>
454
506
/// T1 / const
455
507
/// </summary>
456
508
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
457
- public static GenTensor < T , TWrapper > PiecewiseDivide ( GenTensor < T , TWrapper > a , T b , Threading threading = Threading . Single )
509
+ public static GenTensor < T , TWrapper > PiecewiseDivide ( GenTensor < T , TWrapper > a , T b ,
510
+ Threading threading = Threading . Single )
458
511
=> PiecewiseArithmetics < T , TWrapper > . PiecewiseDivide ( a , b , threading ) ;
459
512
460
513
/// <summary>
461
514
/// const / T1
462
515
/// </summary>
463
516
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
464
- public static GenTensor < T , TWrapper > PiecewiseDivide ( T a , GenTensor < T , TWrapper > b , Threading threading = Threading . Single )
517
+ public static GenTensor < T , TWrapper > PiecewiseDivide ( T a , GenTensor < T , TWrapper > b ,
518
+ Threading threading = Threading . Single )
465
519
=> PiecewiseArithmetics < T , TWrapper > . PiecewiseDivide ( a , b , threading ) ;
466
520
467
521
#endregion
@@ -493,6 +547,40 @@ public GenTensor<T, TWrapper> TensorMatrixPower(int power, Threading threading =
493
547
494
548
#endregion
495
549
550
+ #region Decompositions
551
+
552
+ /// <summary>
553
+ /// https://www.geeksforgeeks.org/l-u-decomposition-system-linear-equations/
554
+ /// </summary>
555
+ /// <returns>
556
+ /// LU decomposition
557
+ /// </returns>
558
+ public ( GenTensor < T , TWrapper > l , GenTensor < T , TWrapper > u ) LuDecomposition ( )
559
+ => LuDecomposition < T , TWrapper > . Decompose ( this ) ;
560
+
561
+ /// <summary>
562
+ /// Find PLU decomposition: matrices P, L, U such that for original matrix A: PA = LU.
563
+ ///
564
+ /// P stands for permutation matrix, permutations are made during the Gauss elimination process
565
+ /// L stands for LIBERTY lower triangle matrix
566
+ /// U stands for upper triangle matrix
567
+ ///
568
+ /// Algorithm, given matrix A:
569
+ /// 1. Form an adjacent matrix (A|E)
570
+ /// 2. Find row echelon form of that matrix (U|L_0) and permutation of the rows
571
+ /// 3. Form permutation matrix P such that P_ij = \delta_{}
572
+ /// 4. Compute L = P * L_0^{-1}
573
+ ///
574
+ /// Results are: P, L, U
575
+ /// </summary>
576
+ /// <returns>
577
+ /// LUP decomposition of given matrix
578
+ /// </returns>
579
+ public ( GenTensor < T , TWrapper > p , GenTensor < T , TWrapper > l , GenTensor < T , TWrapper > u ) PluDecomposition ( )
580
+ => PluDecomposition < T , TWrapper > . Decompose ( this ) ;
581
+
582
+ #endregion
583
+
496
584
#region ToString & GetHashCode
497
585
498
586
/// <inheritdoc/>
@@ -517,7 +605,8 @@ public static GenTensor<T, TWrapper> VectorCrossProduct(GenTensor<T, TWrapper> a
517
605
/// <summary>
518
606
/// Calls VectorCrossProduct for every vector in the tensor
519
607
/// </summary>
520
- public static GenTensor < T , TWrapper > TensorVectorCrossProduct ( GenTensor < T , TWrapper > a , GenTensor < T , TWrapper > b )
608
+ public static GenTensor < T , TWrapper > TensorVectorCrossProduct ( GenTensor < T , TWrapper > a ,
609
+ GenTensor < T , TWrapper > b )
521
610
=> VectorProduct < T , TWrapper > . TensorVectorCrossProduct ( a , b ) ;
522
611
523
612
/// <summary>
@@ -562,6 +651,7 @@ public GenTensor<T, TWrapper> Forward()
562
651
#endregion
563
652
564
653
#region Serialization
654
+
565
655
/*
566
656
* Serialization protocol:
567
657
*
@@ -595,6 +685,7 @@ public byte[] Serialize()
595
685
/// </returns>
596
686
public static GenTensor < T , TWrapper > Deserialize ( byte [ ] data )
597
687
=> Serializer < T , TWrapper > . Deserialize ( data ) ;
688
+
598
689
#endregion
599
690
}
600
- }
691
+ }
0 commit comments