Skip to content

Commit e410541

Browse files
authored
Merge pull request #1216 from Alex-Jordan/matrices-2
update several matrix methods to apply to degree n matrices
2 parents 0666562 + 4519640 commit e410541

File tree

2 files changed

+212
-73
lines changed

2 files changed

+212
-73
lines changed

lib/Value/Matrix.pm

Lines changed: 142 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,17 @@ Examples:
103103
104104
=head3 Access values
105105
106-
row(i) : MathObjectMatrix
107-
For a 1D tensor, produces a 1D tensor
108-
For nD tensor with n > 1, produces a (n-1)D tensor
106+
row(i) : MathObject Matrix
107+
For a degree 1 Matrix, produces a degree 1 Matrix
108+
For a degree n Matrix with n > 1, produces a degree (n-1) Matrix
109109
110-
column(j) : MathObjectMatrix or Real or Complex
111-
For a 1D tensor, produces a Real or Complex
112-
For nD tensor with n > 1, produces an nD tensor where 2nd dimension is 1
110+
column(j) : MathObject Matrix or Real or Complex
111+
For a degree 1 Matrix, produces a Real or Complex
112+
For a degree n Matrix with n > 1, produces a degree n Matrix where the 2nd dimesion is length 1
113113
114-
element : Real or Complex value when passed the same number of arguments as the dimension of the tensor.
115-
If passed more than n arguments, null. If the dimension of the tensor is n and element is passed
116-
k arguments with k < n, then this produces the corresponding (n-k)-dimensional tensor.
114+
element : Real/Complex/Fraction value when passed the same number of arguments as the degree of the Matrix.
115+
If passed more than n arguments, null. If the degree of the Matrix is n and C<element> is passed
116+
k arguments with k < n, then this produces the corresponding degree (n-k) tensor.
117117
118118
=head3 Update values (these need to be added)
119119
@@ -366,7 +366,7 @@ sub isSquare {
366366

367367
=head3 C<isRow>
368368
369-
Return true if the matix is 1-dimensional (i.e., is a matrix row)
369+
Return true if the matix is degree 1 (i.e., is a matrix row)
370370
371371
Usage:
372372
@@ -380,8 +380,7 @@ Usage:
380380

381381
sub isRow {
382382
my $self = shift;
383-
my @d = $self->dimensions;
384-
return scalar(@d) == 1;
383+
return $self->degree == 1;
385384
}
386385

387386
=head3 C<isOne>
@@ -419,26 +418,30 @@ sub isOne {
419418
}
420419
} else {
421420
for my $row (@{ $self->{data} }) {
422-
if (!$row->isOne) {
423-
return 0;
424-
}
421+
return 0 unless $row->isOne;
425422
}
426423
}
427424
return 1;
428425
}
429426

430427
=head3 C<isZero>
431428
432-
Check for zero matrix.
429+
Check for zero Matrix
433430
434431
Usage:
435432
436433
$A = Matrix([ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ], [13, 14, 15, 16] ]);
437-
$A->isZero; # is false
434+
$A->isZero; # is false
438435
439436
$B = Matrix([ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ]);
440437
$B->isZero; # is true;
441438
439+
$C = Matrix([ [ [ 1, 0 ], [ 0, 1 ] ], [ [ 1, 0 ], [ 0, 1 ] ] ]);
440+
$C->isZero; # is false
441+
442+
$D = Matrix([ [ [ 0, 0 ], [ 0, 0 ] ], [ [ 0, 0 ], [ 0, 0 ] ] ]);
443+
$D->isZero; # is true
444+
442445
=cut
443446

444447
sub isZero {
@@ -447,58 +450,99 @@ sub isZero {
447450
return 1;
448451
}
449452

450-
#
451-
# See if the matrix is triangular, diagonal, symmetric, orthogonal
452-
#
453+
=head3 C<isUpperTriangular>
454+
455+
Check if a Matrix is upper triangular (for degree > 2, applies to frontal slice matrices)
456+
457+
=cut
453458

454459
sub isUpperTriangular {
455460
my $self = shift;
456461
my @d = $self->dimensions;
457462
return 1 if scalar(@d) == 1;
458-
return 0 if scalar(@d) > 2;
459-
for my $i (2 .. $d[0]) {
460-
for my $j (1 .. ($i - 1 < $d[1] ? $i - 1 : $d[1])) {
461-
return 0 unless $self->element($i, $j) == 0;
463+
if (scalar(@d) == 2) {
464+
for my $i (2 .. $d[0]) {
465+
for my $j (1 .. ($i - 1 < $d[1] ? $i - 1 : $d[1])) {
466+
return 0 unless $self->element($i, $j) == 0;
467+
}
468+
}
469+
} else {
470+
for my $row (@{ $self->{data} }) {
471+
return 0 unless $row->isUpperTriangular;
462472
}
463473
}
464474
return 1;
465475
}
466476

477+
=head3 C<isLowerTriangular>
478+
479+
Check if a Matrix is lower triangular (for degree > 2, applies to frontal slice matrices)
480+
481+
=cut
482+
467483
sub isLowerTriangular {
468484
my $self = shift;
469485
my @d = $self->dimensions;
470486
if (scalar(@d) == 1) {
471487
for ((@{ $self->{data} })[ 1 .. $#{ $self->{data} } ]) {
472488
return 0 unless $_ == 0;
473489
}
474-
}
475-
return 0 if scalar(@d) > 2;
476-
for my $i (1 .. $d[0] - 1) {
477-
for my $j ($i + 1 .. $d[1]) {
478-
return 0 unless $self->element($i, $j) == 0;
490+
} elsif (scalar(@d) == 2) {
491+
for my $i (1 .. $d[0]) {
492+
for my $j ($i + 1 .. $d[1]) {
493+
return 0 unless $self->element($i, $j) == 0;
494+
}
495+
}
496+
} else {
497+
for my $row (@{ $self->{data} }) {
498+
return 0 unless $row->isLowerTriangular;
479499
}
480500
}
481501
return 1;
482502
}
483503

504+
=head3 C<isDiagonal>
505+
506+
Check if a Matrix is diagonal (for degree > 2, applies to frontal slice matrices)
507+
508+
=cut
509+
484510
sub isDiagonal {
485511
my $self = shift;
486512
return $self->isSquare && $self->isUpperTriangular && $self->isLowerTriangular;
487513
}
488514

515+
=head3 C<isSymmetric>
516+
517+
Check if a Matrix is symmetric (for degree > 2, applies to frontal slice matrices)
518+
519+
=cut
520+
489521
sub isSymmetric {
490522
my $self = shift;
491523
return 0 unless $self->isSquare;
492-
my $d = ($self->dimensions)[0];
493-
return 1 if $d == 1;
494-
for my $i (1 .. $d - 1) {
495-
for my $j ($i + 1 .. $d) {
496-
return 0 unless $self->element($i, $j) == $self->element($j, $i);
524+
my @d = $self->dimensions;
525+
return 1 if $d[-1] == 1;
526+
if (scalar(@d) == 2) {
527+
for my $i (1 .. $d[0] - 1) {
528+
for my $j ($i + 1 .. $d[0]) {
529+
return 0 unless $self->element($i, $j) == $self->element($j, $i);
530+
}
531+
}
532+
} else {
533+
for my $row (@{ $self->{data} }) {
534+
return 0 unless $row->isSymmetric;
497535
}
498536
}
499537
return 1;
500538
}
501539

540+
=head3 C<isOrthogonal>
541+
542+
Check if a Matrix is orthogonal (for degree > 2, applies to frontal slice matrices)
543+
544+
=cut
545+
502546
sub isOrthogonal {
503547
my $self = shift;
504548
return 0 unless $self->isSquare;
@@ -510,52 +554,75 @@ sub isOrthogonal {
510554
return $M->isOne;
511555
}
512556

513-
#
514-
# See if the matrix is in (reduced) row echelon form
515-
#
557+
=head3 C<isREF>
558+
559+
Check if a Matrix is in row echelon form (for degree > 2, applies to frontal slice matrices)
560+
561+
=cut
516562

517563
sub isREF {
518564
my $self = shift;
519565
my @d = $self->dimensions;
520566
return 1 if scalar(@d) == 1;
521-
return 0 if scalar(@d) > 2;
522-
my $k = 0;
523-
for my $i (1 .. $d[0]) {
524-
for my $j (1 .. $d[1]) {
525-
if ($j <= $k) {
526-
return 0 unless $self->element($i, $j) == 0;
527-
} elsif ($self->element($i, $j) != 0) {
528-
$k = $j;
529-
last;
530-
} elsif ($j == $d[1]) {
531-
$k = $d[1] + 1;
567+
if (scalar(@d) == 2) {
568+
my $k = 0;
569+
for my $i (1 .. $d[0]) {
570+
for my $j (1 .. $d[1]) {
571+
if ($j <= $k) {
572+
return 0 unless $self->element($i, $j) == 0;
573+
} elsif ($self->element($i, $j) != 0) {
574+
$k = $j;
575+
last;
576+
} elsif ($j == $d[1]) {
577+
$k = $d[1] + 1;
578+
}
532579
}
533580
}
581+
} else {
582+
for my $row (@{ $self->{data} }) {
583+
return 0 unless $row->isREF;
584+
}
534585
}
535586
return 1;
536587
}
537588

589+
=head3 C<isRREF>
590+
591+
Check if a Matrix is in reduced row echelon form (for degree > 2, applies to frontal slice matrices)
592+
593+
=cut
594+
538595
sub isRREF {
539596
my $self = shift;
540597
my @d = $self->dimensions;
541-
return 1 if scalar(@d) == 1;
542-
return 0 if scalar(@d) > 2;
543-
my $k = 0;
544-
for my $i (1 .. $d[0]) {
545-
for my $j (1 .. $d[1]) {
546-
if ($j <= $k) {
547-
return 0 unless $self->element($i, $j) == 0;
548-
} elsif ($self->element($i, $j) != 0) {
549-
return 0 unless $self->element($i, $j) == 1;
550-
for my $m (1 .. $i - 1) {
551-
return 0 unless $self->element($m, $j) == 0;
598+
if (scalar(@d) == 1) {
599+
for my $i (1 .. $d[0]) {
600+
next if $self->element($i) == 0;
601+
return $self->element($i) == 1 ? 1 : 0;
602+
}
603+
return 1;
604+
} elsif (scalar(@d) == 2) {
605+
my $k = 0;
606+
for my $i (1 .. $d[0]) {
607+
for my $j (1 .. $d[1]) {
608+
if ($j <= $k) {
609+
return 0 unless $self->element($i, $j) == 0;
610+
} elsif ($self->element($i, $j) != 0) {
611+
return 0 unless $self->element($i, $j) == 1;
612+
for my $m (1 .. $i - 1) {
613+
return 0 unless $self->element($m, $j) == 0;
614+
}
615+
$k = $j;
616+
last;
617+
} elsif ($j == $d[1]) {
618+
$k = $d[1] + 1;
552619
}
553-
$k = $j;
554-
last;
555-
} elsif ($j == $d[1]) {
556-
$k = $d[1] + 1;
557620
}
558621
}
622+
} else {
623+
for my $row (@{ $self->{data} }) {
624+
return 0 unless $row->isREF;
625+
}
559626
}
560627
return 1;
561628
}
@@ -850,7 +917,7 @@ sub I {
850917

851918
=head3 C<E>
852919
853-
Get an elementary matrix of the requested size and type. These include matrix that upon left multiply will
920+
Get a degree 2 elementary matrix of the requested size and type. These include matrix that upon left multiply will
854921
perform row operations.
855922
856923
=over
@@ -963,7 +1030,7 @@ sub E {
9631030

9641031
=head3 C<P>
9651032
966-
Creates a permutation matrix of the requested size.
1033+
Creates a degree 2 permutation matrix of the requested size.
9671034
9681035
C<< Value::Matrix->P(n,(cycles)) >> in general where C<cycles> is a sequence of array references
9691036
of the cycles.
@@ -1036,7 +1103,7 @@ sub P {
10361103

10371104
=head3 C<Zero>
10381105
1039-
Create a zero matrix of requested size. If called on existing matrix, creates a matrix as
1106+
Create a degree 2 zero matrix of requested size. If called on existing matrix, creates a matrix as
10401107
the same size as given matrix.
10411108
10421109
Usage:
@@ -1069,7 +1136,8 @@ sub Zero {
10691136

10701137
=head3 C<row>
10711138
1072-
Extract a given row from the matrix.
1139+
Extract a given row from the matrix. For a degree 1 Matrix, $M->row(1) will return $M itself.
1140+
Otherwise, a "row" is defined by the first index. For an degree n Matrix, a "row" will be a degree (n-1) Matrix.
10731141
10741142
Usage:
10751143
@@ -1090,7 +1158,9 @@ sub row {
10901158

10911159
=head3 C<column>
10921160
1093-
Extract a given column from the matrix.
1161+
Extract a given column from the matrix. For a degree 1 Matrix, C<$M->column(j)> will return the jth entry.
1162+
Otherwise, for an degree n Matrix, C<$M->column(j)> returns an degree n Matrix tensor using j for the second index.
1163+
To obtain the corresponding degree (n-1) Matrix, see C<slice()>.
10941164
10951165
Usage:
10961166
@@ -1119,11 +1189,11 @@ sub column {
11191189

11201190
=head3 C<element>
11211191
1122-
Extract an element from the given row/col.
1192+
Extract an element from the given position.
11231193
11241194
Usage:
11251195
1126-
$A = Matrix([ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]);
1196+
$A = Matrix([ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]);
11271197
$A->element(2,3); # returns 7
11281198
11291199
$B = Matrix([ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 5, 6 ], [ 7, 8 ] ] ]);
@@ -1204,6 +1274,8 @@ sub det {
12041274
my $self = shift;
12051275
$self->wwMatrixLR;
12061276
Value->Error("Can't take determinant of non-square matrix") unless $self->isSquare;
1277+
my $n = $self->degree;
1278+
Value->Error("Can't take determinant of degree $n matrix") unless ($n <= 2);
12071279
return Value::makeValue($self->{lrM}->det_LR);
12081280
}
12091281

0 commit comments

Comments
 (0)