Thread Links | Date Links | ||||
---|---|---|---|---|---|
Thread Prev | Thread Next | Thread Index | Date Prev | Date Next | Date Index |
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]_comAs 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.