@@ -669,36 +669,14 @@ sub isREQ {
669669 }
670670 return $lk * $r == $rk * $l ;
671671 } elsif (scalar @ldim == 2) {
672- # get Gram-Schmidt basis for each row space
673- my @rrows = map { $r -> new($_ ) } $r -> value;
674- @rrows = grep { !$_ -> isZero } @rrows ;
675- @rrows = map { $_ / ($_ * $_ )**0.5 } @rrows ;
676- my @rgs = ($rrows [0]);
677- for my $i (1 .. $#rrows ) {
678- my $proj = $r -> new((0) x $rdim [1]);
679- for my $v (@rgs ) {
680- $proj += ($rrows [$i ] * $v ) * $v ;
681- }
682- my $gs = $rrows [$i ] - $proj ;
683- push @rgs , $gs / ($gs * $gs )**0.5 unless $rrows [$i ] == $proj ;
684- }
685- my @lrows = map { $l -> new($_ ) } $l -> value;
686- @lrows = grep { !$_ -> isZero } @lrows ;
687- @lrows = map { $_ / ($_ * $_ )**0.5 } @lrows ;
688- my @lgs = ($lrows [0]);
689- for my $i (1 .. $#lrows ) {
690- my $proj = $r -> new((0) x $ldim [1]);
691- for my $v (@lgs ) {
692- $proj += ($lrows [$i ] * $v ) * $v ;
693- }
694- my $gs = $lrows [$i ] - $proj ;
695- push @lgs , $gs / ($gs * $gs )**0.5 unless $lrows [$i ] == $proj ;
696- }
672+ my @rgs = $r -> NGS;
673+ my @lgs = $l -> NGS;
697674
698675 return 0 if scalar @lgs != scalar @rgs ;
699676
700677 # project each row from $rrows onto @lgs;
701678 # if the complement is nonzero, the row spaces disagree
679+ my @rrows = map { $r -> new($_ ) } $r -> value;
702680 for my $v (@rrows ) {
703681 my $proj = $r -> new((0) x $ldim [1]);
704682 for my $w (@lgs ) {
@@ -707,6 +685,7 @@ sub isREQ {
707685 return 0 unless $v == $proj ;
708686 }
709687 # and vice versa
688+ my @lrows = map { $l -> new($_ ) } $l -> value;
710689 for my $v (@lrows ) {
711690 my $proj = $r -> new((0) x $rdim [1]);
712691 for my $w (@rgs ) {
@@ -726,6 +705,45 @@ sub isREQ {
726705 }
727706}
728707
708+ =head3 C<NGS >
709+
710+ Normalized Gram Schmit basis for a given list of vectors. This uses "fuzzy" equivalency to avoid machine rounding
711+ issues. If called as a method on a Matrix, the rows of that Matrix are used as the list of vectors.
712+
713+ Usage:
714+
715+ $A = Matrix([1, 2, 2], [2, 2, 1]);
716+ $A->NGS # returns [Matrix(1, 2, 2)/3, Matrix(10, 2, -7)/sqrt(153)]
717+
718+ Value::Matrix->NGS([1, 2, 2], [2, 2, 1]) #returns the same as above
719+
720+ =cut
721+
722+ sub NGS {
723+ my ($self , @rows ) = @_ ;
724+ @rows = $self -> value if !@rows && ref ($self ) eq ' Value::Matrix' ;
725+ Value::Error(' You must provide vectors to apply Gram Schmit to' ) if !@rows ;
726+ @rows = map { Value::Matrix-> new($_ ) } @rows ;
727+ @rows = grep { !$_ -> isZero } @rows ;
728+ Value::Error(' You must provide at least one nonzero row for Gram Schmit' ) unless @rows ;
729+ my $n = ($rows [0]-> dimensions)[0];
730+ for my $r (@rows ) {
731+ Value::Error(' Rows provided for Gram Schmit should not be nested arrays' ) unless $r -> degree == 1;
732+ Value::Error(' All rows provided for Gram Schmit should have the same length' ) unless ($r -> dimensions)[0] == $n ;
733+ }
734+ @rows = map { $_ / ($_ * $_ )**0.5 } @rows ;
735+ my @gs = ($rows [0]);
736+ for my $i (1 .. $#rows ) {
737+ my $proj = Value::Matrix-> new((0) x $n );
738+ for my $v (@gs ) {
739+ $proj += ($rows [$i ] * $v ) * $v ;
740+ }
741+ my $gs = $rows [$i ] - $proj ;
742+ push @gs , $gs / ($gs * $gs )**0.5 unless $rows [$i ] == $proj ;
743+ }
744+ return @gs ;
745+ }
746+
729747sub _isNumber {
730748 my $n = shift ;
731749 return Value::isNumber($n ) || Value::classMatch($n , ' Fraction' );
0 commit comments