Am 23.03.2015 um 20:56 schrieb Marco Nehmeier:
Am 23.03.2015 um 19:22 schrieb Oliver Heimlich:
Am 23.03.2015 um 18:14 schrieb John Pryce:
For promotion I'm undecided, and wait for advice from language
experts.
If it's part of the standard, does that make it different at
implementation
level, from making it a consequence of library design and language
features,
e.g., by using class inheritance?
Do you have an example?
No, I am hoping you, Dmitry or Marco can provide some. I was
thinking, suppose in C/C++ one has code like
string s = "[1,2]";
decoratedInterval x;
x = textToInterval(s);
and textToInterval *doesn't* implement line 5 in my text above.
Is there any mechanism in the language to make it try *bare*
textToInterval, after *decorated* textToInterval sees s is not a
decorated literal, and then apply newDec?
Now I think about it, I guess the answer must be No, except by
explicitly coding it into decorated textToInterval.
I can give an example with the GNU Octave interval package (version
0.1.4), where “infsup” implements the bare textToInterval and
“infsupdec” implements the decorated textToInterval.
This implementation automatically promotes bare intervals if the user
calls an operations with mixed arguments, i. e. if at least one
operand is decorated. Whether this has been a good or bad decision
remains to be seen. Demotion does not happen automatically and the
user must explicitly call “intervalpart” for that purpose.
pkg load interval
x = infsup ("[1,2]"); # [1, 2]
y = infsupdec ("[1,2]"); # [1, 2]_com (automatic promotion cf. (5))
z = infsupdec ("[1,2]_dac"); # [1, 2]_dac
y + z # [2, 4]_dac (decorated operation evaluation)
y + x # [2, 4]_com (input x became promoted)
z + x # [2, 4]_dac (input x became promoted)
In my opinion we should avoid implicit conversion between bare and
decorated intervals
as well as using inheritance...
Example.
two classes:
interval
decorated_interval (inherited from interval)
if we have a user function like
interval foo(interval x)
which is only implemented for bare intervals.
In many languages a call of foo with a decorated interval x_d will throw
the the decoration d away
because x_d is an object of decorated_interval which is inherited from
interval. Hence x_d is an interval x.
If we additionally have implicit conversion from interval to
decorated_interval like in Olivers example
than the result of this expression
decorated_interval("[1,2]_com") + foo(
decorated_interval("[4,5]_def") )
has the decoration com.
Marco
Yes, any demotion would be considered an error in that context. Such
an error can also be very dangerous if it is buried unnoticed inside
an interval arithmetic chain of computation.
However, I do not agree with Marco's conclusion to not use inheritance
for that reason. A design that can prevent this kind of error, as used
by libieeep1788, requires a strongly typed language. In any other
language which comes to my mind—except C++—such a design would be a
pain in the neck for developers and probably users too. And for what
cost?
The error presented above with the function foo would be an obvious
one and would not be part of a well tested library. So the function
foo would reside in user space. In order to not return a decorated
interval the function would have to explicitly use a bare interval
constructor, since any return value from correctly working functions
would be decorated. Decorated intervals are an integral part of the
standard and I hope that they will be used by default in the future.
In the example above, any input is decorated, so why should the
function foo be implemented for bare intervals in the first place? And
if so, why is a decorated variant missing?
Let me draw the big picture, why I find automatic promotion so useful.
This has several reasons:
1. It is what the decorated interval constructors do when
decoration information is missing, which I find convenient.
2. The decoration carries information about the course of
computation. If it is missing, it should be introduced. However, that
may also be problematic if it happens too late (*).
3. It simplifies exercising interval arithmetic, when also applied
to coefficients (again for convenience).
For example, it consistently allows the following possibilities when
writing interval arithmetic routines:
pkg load interval
x = infsupdec ("[1,2]"); # [1, 2]_com
x *= 2 # [2, 4]_com (2 became a decorated interval [2, 2]_com)
x += "1.1" # [3.0999999999999996, 5.1000000000000006]_com
# (1.1 became a decorated interval enclosure)
x /= "[1,2]" # [1.5499999999999998, 5.1000000000000006]_com
# ([1,2] became a decorated interval [1, 2]_com)
x -= "[0,Inf]" # [-Inf, +5.1000000000000006]_dac
# ([0,Inf] became a decorated interval [0, Inf]_dac)
(*) However, it also provides a new possibility for the user to shoot
himself in the foot:
x = pow (infsup (0, 1), 0) # [1, 1]
# (a decoration “trv” is missing)
infsupdec ("[1,2]") + x # [2, 3]_com
As you can see in this example, it becomes dangerous to not use
decorated arithmetic by default together with (late) promotion of bare
intervals. As a user I could live with that risk, if I have complete
control over ensuring an uninterrupted decorated computation from
start to finish.
There are valid points for either allowing implicit promotion or not.
I believe we all agree that implicit demotion is bad. If we allow
implicit promotion within the constructors, e.g.
textToInterval("[1,2]") == [1, 2]_com for the decorated variant, it is
consistent to allow it elsewhere too.