|
Boost : |
From: Maarten Kronenburg (M.Kronenburg_at_[hidden])
Date: 2006-06-01 08:06:52
This is the last one in this thread.
The arithmetic non-member operators
returning integer by value are changed
to non-virtual.
The virtual integer & operator=(
const integer & );
now has the following note:
"Derived classes must override this
member operator and use it to convert
(temporary) objects of type integer
back to the derived class."
Also it is explained that the
arithmetic non-member operators and
the arithmetic member operators
returning integer by value must call
integer member functions and operators,
not the derived ones.
Now in expressions with unsigned_integer
variables, temporary results can be
negative. Only when a negative end-result
is assigned, an exception will be thrown.
So when a is 3 and b = 4,
x = -a + b;
will not throw an exception.
Regards, Maarten.
"Maarten Kronenburg" <M.Kronenburg_at_[hidden]> wrote in message
news:e5lb7k$gc8$1_at_sea.gmane.org...
> 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_at_[hidden]> wrote in message
> news:e5ku28$533$1_at_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_at_[hidden]> wrote in message
> > news:e5k7bh$chh$1_at_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_at_[hidden]> wrote in message
> > > news:e5k67i$7hr$1_at_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_at_[hidden]> wrote in message
> > > > news:e5id0q$9ev$1_at_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_at_[hidden]> wrote in message
> > > > > news:e5gvs8$jbm$1_at_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
> >
>
>
>
> _______________________________________________
> Unsubscribe & other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk