OONSTD: Assignment operator =

E. Robert Tisdale (edwin@maxwell.hrl.hac.com)
Mon, 13 Jul 1998 11:32:31 -0700 (PDT)

return type lhs = rhs lhs = rhs
--------------------------------------------------------------------------
<Type><System>SubScalar& subscalar = subscalar subscalar = scalar
<Type><System>SubVector& subvector = subvector subvector = scalar
<Type><System>SubMatrix& submatrix = submatrix submatrix = scalar
<Type><System>SubTensor& subtensor = submatrix subtensor = scalar

Both the left hand side and the right hand side of an assignment operation
must be the same size unless the right hand side is a scalar in which case,
the scalar value is assigned to every element of the left hand side.
For example:

const Length m = 6;
const Length n = 7;

doubleMatrix A(m, n, 1.0); // m by n row major matrix
doubleSubMatrix B = A.t(); // n by m column major matrix
// B references the same 1D array
// referenced by A.
for (Offset i = 0; i < m; i++)
for (Offset j = 0; j < n; j++)
assert(A[i][j] == B[j][i]); // always true

doubleMatrix C = A.t(); // n by m row major matrix
// C references a copy of the 1D array
// referenced by A.
for (Offset i = 0; i < m; i++)
for (Offset j = 0; j < n; j++)
assert(A[i][j] == C[j][i]); // true until A or C is changed

B = 2.0; // assign 2.0 to every element of B

for (Offset i = 0; i < m; i++)
for (Offset j = 0; j < n; j++)
assert(A[i][j] == B[j][i]); // still true

for (Offset i = 0; i < m; i++)
for (Offset j = 0; j < n; j++)
assert(A[i][j] != C[j][i]); // A[i][j] == 2.0 but C[j][i] == 1.0

A = C; // error! A is m by n but C is n by m
A.t() = C; // OK! A.t() and C are both n by m

The assignment operator never changes the size of a vector, matrix or tensor
but application programmers can change the size explicitly using the resize
operator. For example:

A.resize(C); // now A is an n by m row major matrix
// A references a copy of the 1D array
// referenced by C.
B = C; // error! B still references the 1D
// array which has been deallocated
// by A.resize(C).
B.resize(A); // now B references the same 1D array
// referenced by A.
B = C; // OK!

SubVector, SubMatrix and SubTensor objects may have surprising and, we hope,
useful properties because strides can be zero or even negative. For example:

doubleVector R(2*n-1);
R.ramp() -= n-1;
cout << "R = " << setw(2, 2*n-1) << R;

which produces

R = -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6

then, using the constructor

doubleSubMatrix(doubleHandle& h, Offset o, Stride s2, Length n2,
Stride s1, Length n1);

we can view vector R as a matrix:

const
doubleSubMatrix T(R.handle(), n-1, -1, n, +1, n);

cout << "T =\n" << setw(2, n) << T;

which produces

T =
0 1 2 3 4 5 6
-1 0 1 2 3 4 5
-2 -1 0 1 2 3 4
-3 -2 -1 0 1 2 3
-4 -3 -2 -1 0 1 2
-5 -4 -3 -2 -1 0 1
-6 -5 -4 -3 -2 -1 0

Of course, T could appear on the right hand side of an assignment operation
but the result would be undefined if T appeared on the left hand side.
Bob Tisdale