diff --git a/examples/matrix_ex.cpp b/examples/matrix_ex.cpp index 2687091c5..c1791b5c9 100644 --- a/examples/matrix_ex.cpp +++ b/examples/matrix_ex.cpp @@ -34,25 +34,23 @@ int main() // First lets declare these 3 matrices. // This declares a matrix that contains doubles and has 3 rows and 1 column. + // Moreover, it's size is a compile time constant since we put it inside the <>. matrix y; - // Make a 3 by 3 matrix of doubles for the M matrix. - matrix M; - // Make a matrix of doubles that has unknown dimensions (the dimensions are - // decided at runtime unlike the above two matrices which are bound at compile - // time). We could declare x the same way as y but I'm doing it differently - // for the purposes of illustration. - matrix x; + // Make a 3 by 3 matrix of doubles for the M matrix. In this case, M is + // sized at runtime and can therefore be resized later by calling M.set_size(). + matrix M(3,3); - // You may be wondering why someone would want to specify the size of a matrix - // at compile time when you don't have to. The reason is two fold. First, - // there is often a substantial performance improvement, especially for small - // matrices, because the compiler is able to perform loop unrolling if it knows - // the sizes of matrices. Second, the dlib::matrix object checks these compile - // time sizes to ensure that the matrices are being used correctly. For example, - // if you attempt to compile the expression y = M; or x = y*y; you will get - // a compiler error on those lines since those are not legal matrix operations. - // So if you know the size of a matrix at compile time then it is always a good - // idea to let the compiler know about it. + // You may be wondering why someone would want to specify the size of a + // matrix at compile time when you don't have to. The reason is two fold. + // First, there is often a substantial performance improvement, especially + // for small matrices, because the compiler is able to perform loop + // unrolling if it knows the sizes of matrices. Second, the dlib::matrix + // object checks these compile time sizes to ensure that the matrices are + // being used correctly. For example, if you attempt to compile the + // expression y*y you will get a compiler error since that is not a legal + // matrix operation (the matrix dimensions don't make sense as a matrix + // multiplication). So if you know the size of a matrix at compile time + // then it is always a good idea to let the compiler know about it. @@ -67,8 +65,11 @@ int main() 7.8; - // the solution can be obtained now by multiplying the inverse of M with y - x = inv(M)*y; + // The solution to y = M*x can be obtained by multiplying the inverse of M + // with y. As an aside, you should *NEVER* use the auto keyword to capture + // the output from a matrix expression. So don't do this: auto x = inv(M)*y; + // To understand why, read the matrix_expressions_ex.cpp example program. + matrix x = inv(M)*y; cout << "x: \n" << x << endl; @@ -90,11 +91,17 @@ int main() - // The elements of a matrix are accessed using the () operator like so + // The elements of a matrix are accessed using the () operator like so: cout << M(0,1) << endl; // The above expression prints out the value 7.4. That is, the value of // the element at row 0 and column 1. + // If we have a matrix that is a row or column vector. That is, it contains either + // a single row or a single column then we know that any access is always either + // to row 0 or column 0 so we can omit that 0 and use the following syntax. + cout << y(1) << endl; + // The above expression prints out the value 1.2 + // Let's compute the sum of elements in the M matrix. double M_sum = 0; @@ -114,11 +121,6 @@ int main() cout << "sum of all elements in M is " << sum(M) << endl; - // If we have a matrix that is a row or column vector. That is, it contains either - // a single row or a single column then we know that any access is always either - // to row 0 or column 0 so we can omit that 0 and use the following syntax. - cout << y(1) << endl; - // The above expression prints out the value 1.2 // Note that you can always print a matrix to an output stream by saying: diff --git a/examples/matrix_expressions_ex.cpp b/examples/matrix_expressions_ex.cpp index d92e5c855..f85779288 100644 --- a/examples/matrix_expressions_ex.cpp +++ b/examples/matrix_expressions_ex.cpp @@ -81,18 +81,26 @@ int main() x(r,c) = y(r,c) + y(r,c); - This technique works for expressions of arbitrary complexity. So if you - typed x = round(y + y + y + M*y) it would involve no temporary matrices being - created at all. Each operator takes and returns only matrix_exp objects. - Thus, no computations are performed until the assignment operator requests - the values from the matrix_exp it receives as input. - + This technique works for expressions of arbitrary complexity. So if you typed + x = round(y + y + y + M*y) it would involve no temporary matrices being created + at all. Each operator takes and returns only matrix_exp objects. Thus, no + computations are performed until the assignment operator requests the values + from the matrix_exp it receives as input. This also means that statements such as: + auto x = round(y + y + y + M*y) + will not work properly because x would be a matrix expression that references + parts of the expression round(y + y + y + M*y) but those expression parts will + immediately go out of scope so x will contain references to non-existing sub + matrix expressions. This is very bad, so you should never use auto to store + the result of a matrix expression. Always store the output in a matrix object + like so: + matrix x = round(y + y + y + M*y) - There is, however, a slight complication in all of this. It is for statements - that involve the multiplication of a complex matrix_exp such as the following: + In terms of implementation, there is a slight complication in all of this. It + is for statements that involve the multiplication of a complex matrix_exp such + as the following: */ x = M*(M+M+M+M+M+M+M); /*