Daniel said:
Kai-Uwe Bux said:
Daniel said:
From the FAQ: In particular, if these inner array-like objects
end up allocating their own block of memory for their row [or
column] of the matrix, the performance overhead for creating /
destroying your matrix objects can grow dramatically.
If I want to access just one element in the array, must I
create a row or column proxy?
Note the "if" in the FAQ. In reasonable implementations, there
is no overhead for accessing a single element via a proxy.
The "all true Scotsman" fallacy, you are giving "reasonable" a
special definition.
Please note that I do not give any definition for "reasonable".
Of course you do. By your statement you are implying that any
implementation that does not optimize away the overhead for accessing a
single element via a proxy, no matter how standards conforming, or
amazing it may be otherwise, is not "reasonable".
Although my claim implies that, the statement I made is not a definition. I
am ready to encounter reasonable compilers that do not optimize away the
proxies. As soon as that happens, I will consider my statement refuted. If
that statement was a definition, I would not need to be ready for that
possibility.
Would you care to provide an example of a compiler (reasonable or not) that
does not make the optimization under discussion?
You cannot state that all possible standards conforming implementations
make such an optimazation. If an implementation doesn't, it isn't
because there is anything wrong with the implementation.
The optimization techniques needed to do away with small redundant
temporaries that are introduced by code abstractions such a expression
templates or proxy classes are well known, widely implemented, and by no
means cutting edge technology. I agree, however, that failure to implement
these optimizations by and in itself does not mean a compiler is seriously
flawed. I can certainly picture a reasonable compiler failing in this area.
I just happen to think, that such a compiler (although possible) does not
exist.
OK, no "reasonable" Scotsman.
That a statement has implications (in this case my statement implying that
certain compilers are not reasonable) does not turn it into a definition.
My claim would only be a definition if it was to be considered "true by
stipulation". That, however, I something you read into it. I just claimed
it as "factually true": I have never encountered a compiler that did not
optimize away the temporary proxies involved in the test code; the
optimization techniques involved are by now common knowledge among compiler
writers; and I would be surprised to find a reasonable compiler not
implementing them. Here, I stick in "reasonable" just to exclude student
term projects, proofs of concept, alpha versions, discontinued products,
etc.
Had I meant the statement as a definition, I would have worded it
accordingly: "Let us call a compiler 'reasonable' if it optimizes away
small redundant temporaries such a row proxies used in simple element
access." I did not write that because I did not mean it.
I responded by observing that what you quote from the FAQ is a
conditional statement starting with an "if". Such a statement does
not apply whenever the hypothesis is false.
Agreed. However, do you agree with the statemnt made? Is the statement
itself false or true? The FAQ says that *if* the optimazation is
unavailable, then the proxy solution will be slower. Do you agree with
that?
(from FAQ 13.12) If you have a decent compiler and if you
judiciously use inlining, the compiler should optimize away the
temporary objects. In other words, the operator[]-approach
above will hopefully not be slower than what it would have been
if you had directly called Matrix:
perator()(unsigned row,
unsigned col) in the first place. Of course you could have made
your life simpler and avoided most of the above work by
directly calling Matrix:
perator()(unsigned row, unsigned col)
in the first place. So you might as well directly call
Matrix:
perator()(unsigned row, unsigned col) in the first
place.
Is there anything in FAQs 13.10-12 that you specifically object
to? If yes, what is it and why?
I did not address the FAQ. I addressed the virtues of proxies.
In this thread, I have been attempting to defend the veractiy of FAQs
13.10-12.
I think that
A.row(i) += factor*A.row(j);
is much more suggestive notation than
row_of( A, i, j, factor );
Only my refutation of your claim that proxies incur an overhead and
therefore should be avoided for simple element access got us into
FAQ area, and I only responded to the part of the FAQ you quoted.
You were refuting a straw man then. I never claimed that proxies
necessarally incur any overhead. Other than the overhead of actually
writing them of course.
To me the situation looks as follows:
a) proxies provide very useful syntactic sugar for linear algebra.
b) even with very simple minded proxy implementations, [][] is not
slower than (,).
Item (b) is incorrect for all standards conforming compilers,
Did you mean "may be false for some standard conforming compilers"?
Also, do you happen to know an actual standard conforming compiler, for
which the statement (b) is false?
but I will
conceed that it is correct for any compiler you would consider
"reasonable."
You are again misreading my statement for a definition.
As for (a)... Several other languages, including ones that are
spicifically designed for numeric computation and scientific computing
do not use [][]. Beliavsky mentioned in this thread, "[Fortran,] S (the
language of S-Plus and R), Matlab, Python/Numpy, and Visual Basic also
use commas to delimit the dimensions of an array, even when they use []
rather than () to enclose the subscripts. a[j][k] is awkward compared
to a[i,j,k] or a(i,j,k) IMO."
(a) does not talk about [][] versus (,). It talks about the abstraction
benefit that comes with introducing ways of addressing rows and columns of
a matrix. Once you introduce those proxies (for other reasons), operator[]
becomes a nice add-on. There are good reasons to introduce these proxies
independent of supporting [][] notation. Do those languages provide means
for manipulating/addressing rows and columns of a matrix?
Why/how is [][] more "useful" syntacticly than (,)?
It's not---well: asside from generic algorithms templates that could work
with, e.g., double[m][n] as well as any matrix class offering [][].
Personally, I do not put much weight on this feature. Others, who have a
different code base, however, may find this a major point attracting them
to [][] notation.
So what would be the reason, not to provide [][]? Please note that I
do not claim that one should not provide (,).
Again, the FAQ makes no claim that [][] should *not* be provided.
However,
... you could have made your life simpler and avoided most of the
above work [of making proxies] by directly calling
Matrix:
perator()(unsigned row, unsigned col) in the first place. So
you might as well directly call Matrix:
perator()(unsigned row,
unsigned col) in the first place."
Do you disagree with the above?
I disagree with the implied statement that life without row and column
proxies would be easier. The simplicity of my life depends not only on the
code that goes into the matrix class. It mostly depends on the readability
of the code that uses the matrix class. The overhead of the row and column
proxies, as explained above, cannot be eliminated without getting rid of
expressions like
swap( A.row(i), A.row(j) );
and
A.row(i) += f*A.row(j);
Those expressions, however, make my life much easier. My main issue with the
FAQ entry on matrices is that it creates the misguided impression that
element access (although of course an important primitive) is the main
issue in interface design for a matrix class. IMO, how to deal with element
access is a minor issue in the design of a matrix class, and I would just
put in both methods. To be more specific: I would have (,) be provided by a
policy that also defines the storage layout. On top of that, row and column
proxies are realized along with expression template machinery. Then, it is
just a minor add on to have operator[](i) return row(i), following the math
convention that row indices go first.
There are many tricky issues in designing a matrix class (or just its
interface), and the [][] vs (,) issue is none of the interesting ones. The
main flaw of the FAQ is to focus on a minor design issue and draw general
recommendations (e.g., against row proxies) from a rather narrow minded
discussion.
Best
Kai-Uwe Bux