POV-Ray : Newsgroups : povray.general : Function: Making negative numbers positive : Re: Function: Making negative numbers positive Server Time
26 Jun 2024 13:50:29 EDT (-0400)
  Re: Function: Making negative numbers positive  
From: clipka
Date: 27 Nov 2015 14:28:58
Message: <5658aefa$1@news.povray.org>
Am 27.11.2015 um 17:20 schrieb Todd Carnes:
> On 2015-11-27 02:45, clipka wrote:
>> That's only true if the number in question is known to be negative.
>>
> 
> I know, but that was what the OP asked for.
> 
>> In that case, however, it is easier and more efficient to just use the
>> unary minus operator:
>>
>> #declare PositiveNumber = -NegativeNumber;
> 
> That works too, but then it's really just masking the fact that you are
> doing what I said... i.e. multiplying by -1.

No, actually it's just the other way round: Multiplication by -1 is a
negation in a complicated disguise.


Mathematically, the definition of the negative of a value x has nothing
to do with multiplication whatsoever; instead, it is defined as the
inverse of x regarding the addition, i.e. the value that, when added to
x, will result in the neutral element 0.

In other words, the expression

    -x

is defined such that:

    x + (-x) = 0

See? No multiplication involved there. As a matter of fact, in its most
basic form the multiplication operation isn't even /defined/ for
negative numbers; defining whether the product of two negative values
should itself be negative or positive is actually a choice -- it doesn't
follow from first principles (although the choice that such a product
should be positive turns out to be helpful).


In computing, too, arithmetic negation is a well-established operation
in and of itself that has nothing to do with multiplication whatsoever.
CPUs had arithmetic negation operations long before multiplications were
implemented as dedicated machine code operations; earlier computers had
to implement multiplications as a series of additions, but could negate
with ease. And as a matter of fact, in the early days multiplication
functions (and later machine code operations) were sometimes unable to
deal with negative numbers entirely, and to compute the product of two
numbers of arbitrary sign it would have been necessary to first
determine the operands' signs and figure out whether the result should
be negative, then negate any negative operands to get their absolute
value, multiply those, and then negate the result again if it was
supposed to be negative.

In floating-point arithmetics as used by POV-Ray, numbers are typically
stored in sign-and-magnitude format, i.e. there is a bit indicating the
sign of the number, while all the other bits combined indicate the
magnitude. Thus, arithmetic negation is as simple as flipping the sign
bit. Multiplying a number by -1, on the other hand, is as complicated as
multiplying the magnitudes of the operands, and setting the result's
sign bit to the XOR of the operands' sign bits. In this context,
multiplying by 1 is as complicated as multiplying by any other value,
unless the compiler knows in advance that the value is 1 and can
therefore optimize the operation.


In POV-Ray, something even more surprising happens; let's look at the
following statement:

    #declare PositiveNumber = -1 * NegativeNumber;

This is actually equivalent to:

    #declare UNDEFINED_IDENTIFIER = -CONST * FLOAT_IDENTIFIER;

where UNDEFINED_IDENTIFIER happens to be called "PositiveNumber" and is
(presumably) undefined, CONST happens to be 1.0, and FLOAT_IDENTIFIER
happens to be called "NegativeNumber" and (presumably) holds some
negative number.

As you may notice, this statement includes a negation _and_ a
multiplication. The reason is that POV-Ray does not know negative
constants - all it gives you is positive constants and a negation operator.

(The same is also true in the C and C++ programming languages; in their
case, there are even situations where this matters, and can mess up the
code of unsuspecting programmers.)

As POV-Ray is not an optimizing compiler (actually it's no compiler at
all), it resolves the multiplication operation by blindly invoking the
CPU's floating point multiplication machine code operation, even if one
of the operands happens to be 1 in magnitude.

Obviously, multiplying a number with a negated positive constant takes
longer to execute than just negating the number in question -- and it
also takes longer to parse, requiring at least two more tokens (the
numeric literal "1" and the multiplication operator "*").


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.