POV-Ray : Newsgroups : povray.general : Help creating a sgn() function Server Time
2 Aug 2024 02:24:10 EDT (-0400)
  Help creating a sgn() function (Message 1 to 6 of 6)  
From: Jo Jaquinta
Subject: Help creating a sgn() function
Date: 3 Mar 2005 11:49:22
Message: <42274012$1@news.povray.org>
Hey Folks,
   I'm trying to create a sgn() function, like in BASIC. Where sgn(x) = 
-1 if x < 0, +1 if x > 0 and 0 if x = 0.

First I tried with a function:

#declare sgn = function(xx) { #if (xx<0) -1 #else #if (xx>0) 1 #else 0 
#end #end }

But this dies with a "expected 'numeric expression', undeclared 
identifier 'xx' found instead". I take this to mean you can't use a if 
inside a function.

So I tried with a macro:

#macro sgn(xx)
   #if (xx < 0)
     -1
   #else
     #if (xx > 0)
       1
     #else
       0
     #end
   #end
#end

But this gives me a Parse Error: Expected ')', # found instead on the 
"-1" line.

Am I just being really dumb? This should be a no-brainer...

Cheers,

Jo


Post a reply to this message

From: Slime
Subject: Re: Help creating a sgn() function
Date: 3 Mar 2005 12:04:59
Message: <422743bb$1@news.povray.org>
>    I'm trying to create a sgn() function, like in BASIC. Where sgn(x) =
> -1 if x < 0, +1 if x > 0 and 0 if x = 0.

#declare sign = function (x) {select(x,-1,0,1)};

> #declare sgn = function(xx) { #if (xx<0) -1 #else #if (xx>0) 1 #else 0
> #end #end }

Anything that belongs with # is a parse-time command which is evaluated to
*create* the function. The function arguments such as xx are not available
at this time because the function doesn't yet exist. Control structures in a
function can only be created via functions like select().

> So I tried with a macro:
>
> #macro sgn(xx)
>    #if (xx < 0)
>      -1
>    #else
>      #if (xx > 0)
>        1
>      #else
>        0
>      #end
>    #end
> #end

When returning values with a macro, use #local to declare the return value
and then put the variable at the end:

#macro sgn(xx)
   #if (xx < 0)
     #local result = -1;
   #else
     #if (xx > 0)
       #local result = 1;
     #else
       #local result = 0;
     #end
   #end
   result
#end


 - Slime
 [ http://www.slimeland.com/ ]


Post a reply to this message

From: Mike Williams
Subject: Re: Help creating a sgn() function
Date: 3 Mar 2005 15:08:27
Message: <4h693PAx62JCFwe0@econym.demon.co.uk>
Wasn't it Jo Jaquinta who wrote:
>Hey Folks,
>   I'm trying to create a sgn() function, like in BASIC. Where sgn(x) = 
>-1 if x < 0, +1 if x > 0 and 0 if x = 0.
>
>First I tried with a function:
>
>#declare sgn = function(xx) { #if (xx<0) -1 #else #if (xx>0) 1 #else 0 
>#end #end }

You can't use #if inside a function. You need to use "select".

This works:

        #declare sgn=function(xx){select(xx,-1,0,1)}

>But this dies with a "expected 'numeric expression', undeclared 
>identifier 'xx' found instead". I take this to mean you can't use a if 
>inside a function.
>
>So I tried with a macro:
>
>#macro sgn(xx)
>   #if (xx < 0)
>     -1
>   #else
>     #if (xx > 0)
>       1
>     #else
>       0
>     #end
>   #end
>#end
>
>But this gives me a Parse Error: Expected ')', # found instead on the 
>"-1" line.

I don't know the details of why that doesn't work, but you can write it
quite neatly with the "?" operator.

This works:

        #macro sgn(xx) (xx>0?1:(xx<0?-1:0)) #end


-- 
Mike Williams
Gentleman of Leisure


Post a reply to this message

From: Christopher James Huff
Subject: Re: Help creating a sgn() function
Date: 3 Mar 2005 16:27:41
Message: <cjameshuff-5C7609.16274103032005@news.povray.org>
In article <42274012$1@news.povray.org>, Jo Jaquinta <jo### [at] 111georgecom> 
wrote:

>    I'm trying to create a sgn() function, like in BASIC. Where sgn(x) = 
> -1 if x < 0, +1 if x > 0 and 0 if x = 0.

One already exists in math.inc.

-- 
Christopher James Huff <cja### [at] gmailcom>
POV-Ray TAG: <chr### [at] tagpovrayorg>
http://tag.povray.org/


Post a reply to this message

From: kurtz le pirate
Subject: Re: Help creating a sgn() function
Date: 4 Mar 2005 02:44:56
Message: <422811f8$1@news.povray.org>

news:42274012$1@news.povray.org...
> Hey Folks,
>    I'm trying to create a sgn() function, like in BASIC. Where sgn(x) =
> -1 if x < 0, +1 if x > 0 and 0 if x = 0.
>
> First I tried with a function:
>
> #declare sgn = function(xx) { #if (xx<0) -1 #else #if (xx>0) 1 #else 0
> #end #end }
>
> But this dies with a "expected 'numeric expression', undeclared
> identifier 'xx' found instead". I take this to mean you can't use a if
> inside a function.
>
> So I tried with a macro:
>
> #macro sgn(xx)
>    #if (xx < 0)
>      -1
>    #else
>      #if (xx > 0)
>        1
>      #else
>        0
>      #end
>    #end
> #end
>
> But this gives me a Parse Error: Expected ')', # found instead on the
> "-1" line.
>
> Am I just being really dumb? This should be a no-brainer...
>
> Cheers,
>

    and this : #declare sgn=function(xx){xx/abs(xx)} ... of course be
careful
    when xx = 0.


Post a reply to this message

From: Jo Jaquinta
Subject: Re: Help creating a sgn() function
Date: 4 Mar 2005 10:05:33
Message: <4228793d$1@news.povray.org>
Many thanks to everyone for their answers. I didn't know about the 
select() function, that POVRay supported the ? operator, or the math.inc 
function. I've been using POVRay for 10+ years and have a bit of a blind 
spot for new features sometimes. :-)

For the curious, I needed it for a function that creates a bounding box 
for a curved room. I'm tracing the deck plan of the classic Trek 
Enterprise and the rooms are all curved rectangles. I was down to 7 pps 
for one render. I decided that a bounded_by would help. Then the head 
scratching started over the function to create the bounding box!
The function below seems to work. The renders don't seem clipped (see 
"Deck 7" in p.b.i) and the rate has gone up to 135 pps.

Critiques welcome.

Cheers,

Jo


// left & right from POV of center of circle standing on the y+ axis
// leftAngle      : left/anticockwise side
// rightAngle     : right/clockwise side
// insideRadius   : inner wall
// outsideRadius  : outer wall

#macro deck_room_bounds(leftAngle, rightAngle, insideRadius, outsideRadius)
   #local sinLeft = -sin(radians(leftAngle));
   #local cosLeft = cos(radians(leftAngle));
   #local sinRight = -sin(radians(rightAngle));
   #local cosRight = cos(radians(rightAngle));
   #local sgnSinLeft = sgn(sinLeft);
   #local sgnSinRight = sgn(sinRight);
   #local sgnCosLeft = sgn(cosLeft);
   #local sgnCosRight = sgn(cosRight);

   #local 
lowBound=<min(cosLeft*outsideRadius,cosLeft*insideRadius,cosRight*outsideRadius,cosRight*insideRadius)-DECK_WALL_THICK,-e,min(sinLeft*outsideRadius,sinLeft*insideRadius,sinRight*outsideRadius,sinRight*insideRadius)-DECK_WALL_THICK>;
   #local 
highBound=<max(cosLeft*outsideRadius,cosLeft*insideRadius,cosRight*outsideRadius,cosRight*insideRadius)+DECK_WALL_THICK,DECK_HEIGHT+e,max(sinLeft*outsideRadius,sinLeft*insideRadius,sinRight*outsideRadius,sinRight*insideRadius)+DECK_WALL_THICK>;
   #if (sgnSinLeft != sgnSinRight)
     #if (sgnCosLeft < 0) // clip left (-x)
       #local lowBound = 
<-outsideRadius-DECK_WALL_THICK,lowBound.y,lowBound.z>;
     #else // clip right (+x)
       #local highBound = 
<outsideRadius+DECK_WALL_THICK,highBound.y,highBound.z>;
     #end
   #else
     #if (sgnCosLeft != sgnCosRight)
       #if (sgnSinLeft > 0) // clip top (+z)
         #local highBound = 
<highBound.x,highBound.y,outsideRadius+DECK_WALL_THICK>;
       #else // clip bottom (-z)
         #local lowBound = 
<lowBound.x,lowBound.y,-outsideRadius-DECK_WALL_THICK>;
       #end
     #end
   #end
   box { lowBound, highBound }
#end


Post a reply to this message

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