[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
mutable considered harmful, Range edition
From: |
John W. Eaton |
Subject: |
mutable considered harmful, Range edition |
Date: |
Tue, 9 Jun 2020 00:11:05 -0400 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.8.1 |
When using --traditional, I noticed that the result of
zeros (1, 0)
was [](0x0) instead of [](1x0).
This error is related to the use of a mutable cache value in the Range
data type. Here's how:
Constant row vectors (like those produced by zeros and ones) are stored
as ranges with the number of elemnts set to the number of columns and
the increment set to zero.
But using --traditional implies "disable_range (true)" so the
Range::matrix_value method is called is called in the octave_value
constructor and that appears to fail. If I understand correctly, the
matrix_value method returns the incorrect result because it is declared
const but also modifies and returns a mutable value (the cached Matrix
value). The compiler appears to be choosing to return the cache value
before it is modified (the method is const, so normally it wouldn't
change any member variables).
Is it possible to make the mutable cache value reliable in situations
like this? If not, then this appears to be another example of why we
need to eliminate mutable in most places in Octave.
Separately, I see that other than the Range::matrix_value method, we set
the cache value in the operators, like this:
Range operator + (const Range& r, double x)
{
Range result (r.base () + x, r.limit () + x, r.inc (), r.numel ());
if (result.m_numel < 0)
result.m_cache = r.matrix_value () + x;
return result;
}
As I recall, setting the cache in these functions (and not just the
matrix_value method) is done so that, for example, adding a constant to
a range and then converting to a matrix will produce exactly the same
result as converting a range to a matrix and then adding a constant to
the matrix (in psuedo code):
matrix (r) + c == matrix (r + c)
Using the cache this way does avoid the cost of any repeated conversions
to a matrix value, but it also forces the cache to be created for any
operation on a range, not just the result. So it largely defeats the
purpose of the efficient range object storage, and I'm wondering whether
it is worth having a special range data type at all? What do we really
gain for the additional complexity?
jwe
- mutable considered harmful, Range edition,
John W. Eaton <=