Skip to content

Commit dbd6fe7

Browse files
dpvcAlex-Jordan
authored andcommitted
method to set a particular entry in a matrix to a value
1 parent c049913 commit dbd6fe7

2 files changed

Lines changed: 75 additions & 2 deletions

File tree

lib/Value/Matrix.pm

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,14 @@ Examples:
113113
114114
element : Real/Complex/Fraction value when passed the same number of arguments as the degree of the Matrix.
115115
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.
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
120+
set(value, [ i, j, ... ])
121+
For a degree n matrix, the array reference for the second entry should have n elements.
122+
The entry at that location will be replaced with value.
123+
120124
see C<change_matrix_entry()> in MatrixReduce and L<https://wiki.openwebwork.org/moodle/mod/forum/discuss.php?d=2970>
121125
122126
=head3 Advanced
@@ -1342,7 +1346,48 @@ sub element {
13421346
return $M->extract(@_);
13431347
}
13441348

1345-
# @@@ assign @@@
1349+
=head3 C<set>
1350+
1351+
Set a specific element to some value.
1352+
1353+
Usage:
1354+
1355+
$A = Matrix([ [ 1, 2, 3 ], [ 4, 5, 6 ] ]);
1356+
$A->set(7, [ 2, 1 ]);
1357+
# Now $A is the matrix [ [ 1, 2, 3 ], [ 7, 5, 6 ] ]
1358+
1359+
# Also, the method returns the value that is replaced.
1360+
$x = $A->set(8, [ 1, 3 ]);
1361+
# Now $A is [ [ 1, 2, 8 ], [ 7, 5, 6 ] ] and $x is 3.
1362+
1363+
# It is also OK to specify the indices as an array instead of an array reference
1364+
$A->set(7, 2, 1);
1365+
1366+
=cut
1367+
1368+
sub set {
1369+
my ($self, $value, @indices) = @_;
1370+
$value = Value::makeValue($value) unless Value::isValue($value);
1371+
my $dim = $self->degree;
1372+
@indices = @{ $indices[0] } if (ref $indices[0] eq 'ARRAY');
1373+
$self->Error("There should be $dim indices") unless $dim == @indices;
1374+
my $data = $self->{data};
1375+
my $i = pop(@indices) - 1;
1376+
for (my $n = 0; @indices; $n++) {
1377+
my $j = shift(@indices) - 1;
1378+
$self->Error("The " . $self->NameForNumber($n + 1) . " index is outside of the array bounds")
1379+
if $j < 0 || $j >= scalar(@$data);
1380+
$data = $data->[$j]->{data};
1381+
}
1382+
$self->Error("The last index is outside of the array bounds")
1383+
if $i < 0 || $i >= scalar(@$data);
1384+
$self->Error("The new entry value should be " . $data->[$i]->showType . " not " . $value->showType)
1385+
unless $value->type eq $data->[$i]->type;
1386+
my $old = $data->[$i];
1387+
$data->[$i] = $value;
1388+
return $old;
1389+
}
1390+
13461391
# @@@ removeRow, removeColumn @@@
13471392
# @@@ Minor @@@
13481393

t/math_objects/matrix.t

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,34 @@ subtest 'Extract a column' => sub {
215215
}, qr/Column must be a positive integer/, 'Test that an error is thrown for passing a non-positive integer';
216216
};
217217

218+
subtest 'Set a value' => sub {
219+
my $A = Matrix([ 1, 2, 3 ]);
220+
my $B = Matrix([ [ 1, 2, 3 ], [ 4, 5, 6 ] ]);
221+
my $C = Matrix([ [ 1, 2, 3 ], [ 4, 5, 6 ] ]);
222+
my $D = Matrix([ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 5, 6 ], [ 7, 8 ] ] ]);
223+
224+
is $A->set(9, [2]), 2, 'Replace an element from a degree 1 matrix, returning replaced element';
225+
is $A->TeX, Matrix([ 1, 9, 3 ])->TeX, 'Replace an element from a degree 1 matrix';
226+
is $B->set(9, [ 2, 1 ]), 4, 'Replace an element from a degree 2 matrix, returning replaced element';
227+
is $B->TeX, Matrix([ [ 1, 2, 3 ], [ 9, 5, 6 ] ])->TeX, 'Replace an element from a degree 2 matrix';
228+
is $C->set(9, 2, 1), 4, 'Replace an element from a degree 2 matrix, returning replaced element';
229+
is $C->TeX, Matrix([ [ 1, 2, 3 ], [ 9, 5, 6 ] ])->TeX, 'Replace an element from a degree 2 matrix';
230+
is $D->set(9, [ 2, 1, 2 ]), 6, 'Replace an element from a degree 3 matrix, returning replaced element';
231+
is $D->TeX, Matrix([ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 5, 9 ], [ 7, 8 ] ] ])->TeX,
232+
'Replace an element from a degree 3 matrix';
233+
234+
like dies {
235+
$B->set(10, [ 1, 2, 3 ]);
236+
}, qr/There should be 2 indices/, 'Check correct number of indices passed';
237+
like dies {
238+
$B->set(10, [ 3, 1 ]);
239+
}, qr/The first index is outside of the array bounds/, 'Check index is within bounds';
240+
like dies {
241+
$B->set(Point(1, 2), [ 2, 1 ]);
242+
}, qr/The new entry value should be a Number not a Point/, 'Check replaced value has the same type';
243+
244+
};
245+
218246
subtest 'Construct an identity matrix' => sub {
219247
my $I = Value::Matrix->I(3);
220248
my $B = Matrix([ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ]);

0 commit comments

Comments
 (0)