POV-Ray : Newsgroups : povray.advanced-users : select, pow(0,0) Server Time
28 Mar 2024 17:08:25 EDT (-0400)
  select, pow(0,0) (Message 1 to 5 of 5)  
From: Bald Eagle
Subject: select, pow(0,0)
Date: 25 Aug 2018 12:45:01
Message: <web.5b8186d1724f2371458c7afe0@news.povray.org>
So, I'm trying to write some macros that use pow(X, V).
I'm trying to make it past the "domain error" when pow(0,0) occurs.

So I tried:
#local PowX = select (X * V * (1-X), 0, 0, pow(X, V) );
But that gave me the same error, presumably because select evaluates the full
expression even though the threshold switch won't implement the >0 result.

So I finally did the following:

#declare E = 0.0000001;
#local PowX = select ((X * V * (1-X))-E, 0, 0, pow(X+E, V) );

#local Pow1minX = select ((1-X)*(N-V), 0, 0, pow((1-X),(N-V)) );

At some point X=1, and so 1-1=0, and you'd expect to get the same domain error,
but that doesn't happen.

Is there a better, more elegant way to do this?

Is this a floating point thing again - out at the 15th decimal place?

Isn't there a pow function that tolerates / passes through pow(0,0) as 0, like
the magical atan2 ?

I must say that it get get REALLY frustrating to get bogged down in fixing
things that you wouldn't have thought needed fixing, just so you can get back to
the point of working on the ACTUAL math that you started trying to fix.


Post a reply to this message

From: clipka
Subject: Re: select, pow(0,0)
Date: 25 Aug 2018 13:39:53
Message: <5b819469@news.povray.org>
Am 25.08.2018 um 18:41 schrieb Bald Eagle:
> 
> So, I'm trying to write some macros that use pow(X, V).
> I'm trying to make it past the "domain error" when pow(0,0) occurs.
> 
> So I tried:
> #local PowX = select (X * V * (1-X), 0, 0, pow(X, V) );
> But that gave me the same error, presumably because select evaluates the full
> expression even though the threshold switch won't implement the >0 result.
> 
> So I finally did the following:
> 
> #declare E = 0.0000001;
> #local PowX = select ((X * V * (1-X))-E, 0, 0, pow(X+E, V) );
> 
> #local Pow1minX = select ((1-X)*(N-V), 0, 0, pow((1-X),(N-V)) );
> 
> At some point X=1, and so 1-1=0, and you'd expect to get the same domain error,
> but that doesn't happen.

Are you sure that N-V=0, too?

> Is there a better, more elegant way to do this?

In a macro? Why, yes, of course! Why not use `#if` instead of `select`?

> Isn't there a pow function that tolerates / passes through pow(0,0) as 0, like
> the magical atan2 ?

And what result should that function return?

In some applications, you may want the result to be 1, to conform with
x^0=1; in other applications, a result of 0 would make more sense, to
conform with 0^x=0.

And in yet other applications, the most sensible thing to do is catch
this case further upstream and report that something's just totally wrong.


Post a reply to this message

From: Bald Eagle
Subject: Re: select, pow(0,0)
Date: 25 Aug 2018 17:25:01
Message: <web.5b81c8dd94148acd458c7afe0@news.povray.org>
clipka <ano### [at] anonymousorg> wrote:

I take it that's an implied confirmation that select() evaluates all the return
arguments before returning the conditional result.

> Are you sure that N-V=0, too?

"Yes."   #for (V, 0, N)....
So N-V when V=N _should_ indeed "equal zero"
But I'm in the middle of debugging the chain-linked macros I've coded, so I
shall find out for certain.
Right now, I'm making them more svelt.  More chain-link, less barbed-wire.

> In a macro? Why, yes, of course! Why not use `#if` instead of `select`?

Because that seemed iffy?  :P

I like to branch out and sample the different methods of doing things, and keep
my function {} skills unatrophied.   :P

Because sometimes I just don't like the if-[then]-else-end block and select()
seemed visually neater.   And every little thing that's not distracting helps.



> > Isn't there a pow function that tolerates / passes through pow(0,0) as 0, like
> > the magical atan2 ?
>
> And what result should that function return?

Bags of hundred dollar bills.


Oh, how I could have bet money that this question would be asked...   :D

> In some applications, you may want the result to be 1, to conform with
> x^0=1;

pow1 (x, 0) = 1

> in other applications, a result of 0 would make more sense, to
> conform with 0^x=0.

pow0 (x,0) = 1

> And in yet other applications, the most sensible thing to do is catch
> this case further upstream and report that something's just totally wrong.

pow (x, 0) = undefined, out of range, error, nil, nul, whatever you'd like.
Maybe just make it a warning.

roll it up to include all three:

pow (x, 0, Mode)

Something.  I just think that 25-year-old legendary software ought to be mature
enough to not require the user to code their way out of something that should
only require a switch or the trivial documented use of an alternate function -
like with atan() and atan2().


Post a reply to this message

From: clipka
Subject: Re: select, pow(0,0)
Date: 25 Aug 2018 17:45:15
Message: <5b81cdeb$1@news.povray.org>
Am 25.08.2018 um 23:23 schrieb Bald Eagle:

> I take it that's an implied confirmation that select() evaluates all the return
> arguments before returning the conditional result.

I can confirm for `select()` in normal SDL expressions. For use of
`select()` in functions I'd have to dig deeper.


Post a reply to this message

From: clipka
Subject: Re: select, pow(0,0)
Date: 25 Aug 2018 18:51:23
Message: <5b81dd6b$1@news.povray.org>
Am 25.08.2018 um 23:23 schrieb Bald Eagle:

> Right now, I'm making them more svelt.  More chain-link, less barbed-wire.

I had to look that up.

> Something.  I just think that 25-year-old legendary software ought to be mature
> enough to not require the user to code their way out of something that should
> only require a switch or the trivial documented use of an alternate function -

Name any respectable programming language that provides workarounds for
the pow(0,0) problem out of the box.

> like with atan() and atan2().

That's a whole different game. Technically, `atan2()` is an answer to a
very different question than `atan()`.

`atan(x)` gives the answer to the quite academic question, "what is the
arcus tangens of x, as per the mathematical definition?"

`atan2(y,x)` gives the answer to the far more practical question, "what
is the angle between the X axis and a ray from (0;0) to (x;y) in
cartesian space, as per geometric properties?". Its name derives from
the fact that the answer /happens/ to coincide with `atan(y/x)` for
positive x (and that the function takes 2 arguments), but it really is a
fundamentally different question.

While this latter question could be rephrased in terms of the former one
plus some extra steps, it occurs so frequently that having a dedicated
stock function for it is perfectly warranted.

The `pow()` case is totally different: There is no corresponding
practical question that would require graceful handling of the special
case equivalent to `pow(0,0)` while also being asked frequently enough
to warrant a dedicated stock function.

And thus, to the best of my knowledge there is no program language of
any renown that has such a function. Whether you use POV-Ray's SDL,
C/C++, Fortran, Java, C#, Python, Ruby, Go, Lolcode, or what-have-you,
you will always have to do special handling if your algorithm involves
computing `pow(a,b)` with a and b potentially being both zero.

In contrast, `atan2` has been around at least since the 1970s, and has
spread from Fortran 77 to pretty much any language of renown that is
frequently used for mathematically-oriented applications (including
POV-Ray's SDL, C/C++, Java, C#, Python, Ruby and Go, and probably also
what-have-you).


Fun fact: Although `atan2` (aka `arctan2`) originally started out as a
shortcut software function, nowadays it appears to be considered a
full-fledged mathematical function in its own right.


Post a reply to this message

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