
There is another solution: in the binary integer operators the lhs or rhs is cloned, but not the derived member operators are called, but the integer ones. This seems reasonable as the binary integer operators return integers by value anyway. Also the unary operator- returns integer by value, and can call the integer negate(), not the derived one. Only when the result is assigned, the derived operator=( const integer & ) is called, which converts the integer back to the derived class, and in the case of unsigned_integer, throw an exception when the result is negative. This solves our unsigned_integer problem. There is however one price: efficiency. For example for modular_integer, the temporary results are never made modular, so may become larger than when the derived member operators would have been called. So this is another dilemma. But as those integer arithmetic binary and unary operators return integer by value anyway, in my opinion the integer member operators should be called, and not the derived ones, although this may be less efficient in some cases. Regards, Maarten. "Maarten Kronenburg" <M.Kronenburg@inter.nl.net> wrote in message news:e5ku28$533$1@sea.gmane.org...
This problem with unsigned_integer throwing an exception when negative is already apparent for the two expressions a-b and -a+b When the integer binary operator- would clone the lhs, then the second effectively does a negate, but the first does not. Then the first would not throw an exception, but the second would. When because of this problem the unsigned_integer goes, then the user can only make an unsigned integer by using the modular_integer and setting its modulus (for example to 2^n). But as this would limit the values to under 2^n, it is not really infinite precision anymore. So we have a dilemma: or we have a true unsigned infinite precision integer which may or may not throw exceptions in equivalent expressions, or we only have an unsigned integer which is actually a modular integer with a modulus, so which is not really infinite precision. But the modular_integer will be there anyway, which may serve as an unsigned integer by: typedef modular_integer unsigned_integer; Regards, Maarten.
"Maarten Kronenburg" <M.Kronenburg@inter.nl.net> wrote in message news:e5k7bh$chh$1@sea.gmane.org...
The situation is a little bit different. The integer binary operators like operator+ and operator- return an integer, so the type of these temporaries is integer. Each type derived from type integer has an operator=( const integer & ) which converts the temporary integer back to the derived type. So after assigning the result, the result is identical. Then there are the temporaries that are cloned inside the integer binary operators, and the corresponding virtual member function is called of this clone. Because the binary operator must choose which object to clone, the rhs or the lhs, the values of these clones and the values of the integer temporaries can be different between a-b-c and a-(b+c). So the values of the clones and the integer temporaries can be different anyway, but as the unsigned_integer throws and exception when it becomes negative, the brackets may decide whether an exception is thrown. The question is if this can be accepted, if not the unsigned_integer must go. In the document I will also mention this issue. Regards, Maarten.
"Maarten Kronenburg" <M.Kronenburg@inter.nl.net> wrote in message news:e5k67i$7hr$1@sea.gmane.org...
Because the integer binary operators must clone the rhs OR the lhs, the temporaries in expressions can be of type integer OR derived type. Now as each derived type has an operator=( const integer & ) which turns the integer temporary back to the derived type, the result after assignment is always identical. But the temporaries can still be either integer type or derived type. This expression a-b-c can have another type of temporary then a-(b+c) However which type it is is independent of compiler, because of the [expr.add] remark. Now the question is that because unsigned_integer throws an exception when it becomes negative, is it acceptable that when a and b nonzero, a-b-c then throws an exception and a-(b+c) not? Regards, Maarten.
"Maarten Kronenburg" <M.Kronenburg@inter.nl.net> wrote in message news:e5id0q$9ev$1@sea.gmane.org...
There is however one catch to the unsigned_integer: the expression a-b-c Then look in [expr.add]: "The additive operators group from left-to-right". The integer binary operator- first clones the rhs, negates it, and then adds to it the lhs. This guarantees that when b or c are non-zero unsigned_integer, then ALWAYS an exception is thrown. BUT what about a-(b+c) Now (b+c) returns a temporary integer (not unsigned_integer), which is negated (NO exception) and a is added to it. So although the behaviour is compiler-independent because of the [expr.add] remark, the use of braces in expressions may change the behaviour of an unsigned_integer expression, that is while a-b-c may throw an exception, a-(b+c) may not. Regards, Maarten.
"Maarten Kronenburg" <M.Kronenburg@inter.nl.net> wrote in message news:e5gvs8$jbm$1@sea.gmane.org...
If you don't mind I start a new thread here. The unsigned infinite precision integer is different from the base type unsigned int, which is actually a modular integer with modulus 2^n. Therefore two integer derived classes are needed: unsigned_integer and modular_integer. The unsigned_integer is an infinite precision integer which can only be positive or zero. The negate() of a non-zero unsigned_integer will always throw an exception. A subtraction which results in a negative value will do the same; therefore in my opinion there is no fundamental problem with this, as negation is subtraction from zero. The modular_integer has a static method static void set_modulus( const integer & ). When the modulus is not set, it is zero, in that case the modular_integer is identical to integer. Users that like an unsigned integer with a negate() that always works, will have to use a modular_integer and set its modulus to a positive value. In the document I will specify unsigned_integer and modular_integer, and thus implementations can provide them. Regards, Maarten.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost