On Saturday, 15 February 2014 at 23:06:27 UTC, Robin wrote:
Matrix is still a class but I changed it to a final class
preventing matrix methods to be virtual. Dimension is now a
final struct (don't know if 'final' is affecting structs in any
way tough ...).
It doesn't. It may even be disallowed someday, when it's fixed :)
This mainly gave the multiplication a huge performance boost.
When converting the Matrix to a struct from class the
multiplication even lowered from ~4.3 seconds to about 3.6
seconds. However, I am currently not sure if I want matrices to
be structs (value types).
Make them value types. If you're using dynamic arrays for
storage, you're already using GC plenty, no need for additional
allocations (and see below for copy and move semantics). Don't
forget a postblit though.
(In the C++ matrix codes this scenario would actually call move
assignment operator for matrix m3 which is much much faster
than copying.)
D performs return value optimization: it moves result whenever it
can.
But I haven't figured out yet how to use move semantics in D
with class objects. Or is that just possible with struct value
types?
Yup, it "just works". In most cases, anyway.
But move semantics in D differ from C++: D doesn't have rvalue
references, and thus the compiler only performs a move when it
can prove that value will no longer be used (there's a lengthy
description in TDPL but I'm too lazy now to fetch it for exact
citation :) ).
For explicit moves, there's std.algorithm.move(), though AFAIK
it's underimplemented at the moment.
I have also tried the LDC compiler. However, it gave me some
strange bugs. E.g. it didn't like the following line:
ref Matrix transpose() const {
return new Matrix(this).transposeAssign();
}
And it forced me to change it to:
ref Matrix transpose() const {
auto m = new Matrix(this);
m.transposeAssign();
return m;
}
Which is kind of ugly ...
I hope that this is getting fixed soon, as I imply it as
correct D code because the DMD is capable to compile this
correctly.
Yes, this should be allowed. But you could also just write (new
Matrix(this)).transposeAssign() :)
Also, there's no point in ref return when you're returning a
reference to class instance.
T opIndex(in size_t row, in size_t col) const nothrow
in {
assert(row < nRows);
assert(col < nCols);
} body {
return data[dim.offset(row, col)];
}
The in and body statements are cool as far as I realize what
they are for. ...so I think that the compiler won't optimize
things in an 'in' code block - is that right?
in/out contracts are debug creatures anyway, they're not present
in -release builds.