POV-Ray : Newsgroups : povray.advanced-users : problem using ORs and strcmp() in #switch/#case Server Time
17 May 2024 02:55:22 EDT (-0400)
  problem using ORs and strcmp() in #switch/#case (Message 7 to 16 of 36)  
<<< Previous 6 Messages Goto Latest 10 Messages Next 10 Messages >>>
From: Kenneth
Subject: Re: problem using ORs and strcmp() in #switch/#case
Date: 7 Nov 2017 17:25:00
Message: <web.5a022f2a1346e9e089df8d30@news.povray.org>
"Kenneth" <kdw### [at] gmailcom> wrote:
> ...That's why I didn't use #switch(TRUE)-- also because, with *that*,
> the overal results--when USING the ORs--were screwy in a different way!
>

An interesting example of that:

In my code, change...
#switch(1000)
#case((strcmp(IMG_TYPE,AA) + 1000)
       | (strcmp(IMG_TYPE,BB) + 1000)
       | (strcmp(IMG_TYPE,CC) + 1000)
     )

to...
#switch(true)
#case(
       // no (strcmp(IMG_TYPE,AA), which is the only 'correct' match
       (strcmp(IMG_TYPE,BB))
       | (strcmp(IMG_TYPE,CC))
     )

This still produces a 'true' result (the GREEN box), when neither of the #case
comparisons actually 'match'. BUT... it occurs to me that a matching 'true'
value could be ANY number (positive or negative!), just so long as it's not a
zero-- which would be a 'false' result.


Post a reply to this message

From: Bald Eagle
Subject: Re: problem using ORs and strcmp() in #switch/#case
Date: 7 Nov 2017 18:20:01
Message: <web.5a023e9f1346e9e05cafe28e0@news.povray.org>
You're ---- thinking about #switch and #case() in an --- odd way.

I see where it's going wrong, and this will give you an idea of why:

    #switch(true)

    #case(1)
     rgb <0, 0, 0.2>
    #break

    #case(
       // no (strcmp(IMG_TYPE,AA), which is the only 'correct' match
       (strcmp(IMG_TYPE,BB))
       | (strcmp(IMG_TYPE,CC))
     )

#switch(true) is a very strange usage, and I'm sure clipka could give some
source-code explanation of why it works the way it does.
But basically, as I suspected, it just selects the FIRST #case() regardless of
what it is.

In fact, check out:

    #switch(strcmp(IMG_TYPE,BB) | strcmp(IMG_TYPE,CC) )

     #case(-10)
     rgb <1, 1, 0>
    #break

     #case(-6)
     rgb <1, 1, 1>
    #break

    #case(1)
     rgb <0, 0, 0.2>
    #break

    #case(1000)

It selects the blue pigment, which corresponds to 1.


So, I think you need to do something along the lines of

#declare IMG_TYPE = (some string operator on your filename)
#if IMG_TYPE = "jpg"  #local AA = 1; #end
#if IMG_TYPE = "png"  #local AA = 2; #end
#if IMG_TYPE = "tiff" #local AA = 3; #end

#select (AA)

.....


OR, since if any one of the cases you want to select for is going to yield a
value of zero for strcmp(),

#declare Pig = strcmp(IMG_TYPE,AA) * strcmp(IMG_TYPE,BB) * strcmp(IMG_TYPE,CC);

and then #select (Pig)

(that works for me)


Post a reply to this message

From: clipka
Subject: Re: problem using ORs and strcmp() in #switch/#case
Date: 7 Nov 2017 20:44:53
Message: <5a026195$1@news.povray.org>
Am 07.11.2017 um 20:32 schrieb Kenneth:

>     #switch(1000)
>     #case(
>     // INDIVIDUALLY, these all work the way they are supposed to-- but not
>     // all three at once. The OR's are causing some kind of problem, and
>     // the result always fall through to the #else clause.
>         (strcmp(IMG_TYPE,AA) + 1000)
>         | (strcmp(IMG_TYPE,BB) + 1000)
>         | (strcmp(IMG_TYPE,CC) + 1000)
>          )

Ah... yes... no, don't do that.

The `#switch`/`#case` construct is designed to be used as follows:

    // (A)
    #switch(VARIABLE)
      #case(CONST1)
        // go here if VARIABLE = CONST1
      #break
      #case(CONST2)
        // go here if VARIABLE = CONST2
      #break
      ...
    #end

It so happens that the `#case` values /can/ be other variables (and of
course the `#switch` value /can/ be a constant), allowing for a hack to
co-opt the statement as a replacement for pathologic `#if... #else #if
... #end #end` nesting:

    // (B)
    #switch(true)
      #case(CONDITION1)
        // go here if CONDITION1 is true
      #break
      #case(CONDITION2)
        // otherwise go here if CONDITION2 is true
      #break
      ...
    #end

If the conditions are string equality tests (`strcmp(...)=0`), the
following similar construct is also possible:

    // (C)
    #switch(0)
      #case(strcmp(STRING,CONST1))
        // go here if STRING = CONST1
      #break
      #case(strcmp(STRING,CONST2))
        // otherwise go here if STRING = CONST2
      #break
      ...
    #end

Note however that (B) and (C) *do not mix* nicely -- you have to decide
whether you want your `#case` expressions to be logical tests (allowing
for logical OR, AND etc.) or `strcmp()` results. You can't just try to
mix them (unless you know exactly what you're doing).

Also, there's a much easier way to achieve a logical OR in any `#switch`
construct: Just place multiple `#case` statements without a `#break` in
between, like so:

    #switch(0)
      #case(strcmp(STRING,CONST1A))
      #case(strcmp(STRING,CONST1B))
        // go here if STRING = CONST1A or CONST1B
      #break
      #case(strcmp(STRING,CONST2A))
      #case(strcmp(STRING,CONST2B))
        // otherwise go here if STRING = CONST2A or CONST2B
      #break


Finally, note that as of v3.7, (B) and (C) can be rewritten as:

    // (B)
    #if(CONDITION1)
      // go here if CONDITION1 is true
    #elseif(CONDITION2)
      // otherwise go here if CONDITION2 is true
    ...
    #end

    // (C)
    #if(STRING = CONST1)
      // go here if STRING = CONST1
    #elseif(STRING = CONST2)
      // otherwise go here if STRING = CONST2
    ...
    #end


> Perhaps I shouldn't be using strcmp() at all. It *is* a rather complex beast--

Indeed (though with the `+1000` term you're overcomplicating things).

As of v3.7, the various comparison operators (`=`, `<` etc.) are a much
better choice in most cases, now that they also support strings.


Post a reply to this message

From: Bald Eagle
Subject: Re: problem using ORs and strcmp() in #switch/#case
Date: 7 Nov 2017 21:50:00
Message: <web.5a026fc91346e9e05cafe28e0@news.povray.org>
clipka <ano### [at] anonymousorg> wrote:

> Also, there's a much easier way to achieve a logical OR in any `#switch`
> construct: Just place multiple `#case` statements without a `#break` in
> between, like so:
>
>     #switch(0)
>       #case(strcmp(STRING,CONST1A))
>       #case(strcmp(STRING,CONST1B))
>         // go here if STRING = CONST1A or CONST1B
>       #break
>       #case(strcmp(STRING,CONST2A))
>       #case(strcmp(STRING,CONST2B))
>         // otherwise go here if STRING = CONST2A or CONST2B
>       #break

Yes, I had considered mentioning this possibility (I've discovered it
accidentally by failing to include the #break(s)  :O, so I'm glad you provided
this example.

Thanks for all of the other examples - useful stuff and a very good supplement
to the official docs   :)


Post a reply to this message

From: Kenneth
Subject: Re: problem using ORs and strcmp() in #switch/#case
Date: 7 Nov 2017 23:00:00
Message: <web.5a0281171346e9e089df8d30@news.povray.org>
"Bald Eagle" <cre### [at] netscapenet> wrote:
>
> I see where it's going wrong, and this will give you an idea of why:
>
>     #switch(true)
>
>     #case(1)
>      rgb <0, 0, 0.2>
>     #break
>
>     #case(
>        // no (strcmp(IMG_TYPE,AA), which is the only 'correct' match
>        (strcmp(IMG_TYPE,BB))
>        | (strcmp(IMG_TYPE,CC))
>      )
>
> #switch(true) is a very strange usage, and I'm sure clipka could give some
> source-code explanation of why it works the way it does.
> But basically, as I suspected, it just selects the FIRST #case() regardless of
> what it is.

But here's a very similar example (though without any ORs, which might make all
the difference), and it selects the 2nd #case (green)...

#switch(true)
#case(0)
     rgb <0, 0, 0.2> // BLUE
#break
#case(1)
    rgb <0,1,0> // GREEN
#break
....

This makes sense to me (well, at the moment, anyway!), as it looks like
#switch(true) is picking the #case with the appropriate 'true' result of (1)
>
> In fact, check out:
>
>     #switch(strcmp(IMG_TYPE,BB) | strcmp(IMG_TYPE,CC) )
>
>      #case(-10)
>      rgb <1, 1, 0>
>     #break
>
>      #case(-6)
>      rgb <1, 1, 1>
>     #break
>
>     #case(1)
>      rgb <0, 0, 0.2>
>     #break
>
>     #case(1000)
>
> It selects the blue pigment, which corresponds to 1.

*That's* a really unexpected result, IMO; neither of the #switch's strcmp()s
'match' IMG_TYPE (which would be AA), yet #case(1) is chosen as if #switch is
'true.' And looking at it in a different brain-twisting way (one that's
incorrect, no doubt), it seems that either #case(-6) or #case(-10) should be
chosen, but certainly not #case(1)

It all makes my brain hurt :-O


Post a reply to this message

From: Kenneth
Subject: Re: problem using ORs and strcmp() in #switch/#case
Date: 7 Nov 2017 23:45:00
Message: <web.5a028a351346e9e089df8d30@news.povray.org>
clipka <ano### [at] anonymousorg> wrote:


>
> Also, there's a much easier way to achieve a logical OR in any `#switch`
> construct: Just place multiple `#case` statements without a `#break` in
> between, like so:
>
>     #switch(0)
>       #case(strcmp(STRING,CONST1A))
>       #case(strcmp(STRING,CONST1B))
>         // go here if STRING = CONST1A or CONST1B
>       #break
>       #case(strcmp(STRING,CONST2A))
>       #case(strcmp(STRING,CONST2B))
>         // otherwise go here if STRING = CONST2A or CONST2B
>       #break
>
I didn't know that using #cases without #breaks was possible :-O  Thanks! That's
the construction I will probably use; it's nice and elegant. In fact, so
interesting that a note in the documentation about it would be justified ;-)

BTW, I almost never use #switch(true) in my scenes, usually just #switch(1) or
#switch(0)-- believing that they are the 'logical equivalents' of true/false,
not just the 'number values' 1 and 0. It has always worked for me, but is my
assumption valid, in light of all that's been said?

Another question, just to clarify something: Is there a difference between the
following two examples? (I don't actually code the latter way-- it may not even
be appropriate-- but I've seen various types of non-strcmp() constructions in
the newsgroups that look similar)...

#switch(0)
#case(strcmp(IMG_TYPE,AA))

and

#switch(0)
#case(strcmp(IMG_TYPE,AA)=0)

I ask because the latter doesn't work--no error message of any kind is created,
but it falls through to the #else clause, even though strcmp(IMG_TYPE,AA) is a
'match' between IMG_TYPE and AA.


Post a reply to this message

From: Bald Eagle
Subject: Re: problem using ORs and strcmp() in #switch/#case
Date: 8 Nov 2017 06:20:01
Message: <web.5a02e7b51346e9e05cafe28e0@news.povray.org>
"Kenneth" <kdw### [at] gmailcom> wrote:

> But here's a very similar example (though without any ORs, which might make all
> the difference), and it selects the 2nd #case (green)...
>
> #switch(true)
> #case(0)
>      rgb <0, 0, 0.2> // BLUE
> #break
> #case(1)
>     rgb <0,1,0> // GREEN
> #break
> ....
>
> This makes sense to me (well, at the moment, anyway!), as it looks like
> #switch(true) is picking the #case with the appropriate 'true' result of (1)

Right.  "true" "on" "yes" all evaluate to 1 in SDL.


> *That's* a really unexpected result, IMO; neither of the #switch's strcmp()s
> 'match' IMG_TYPE (which would be AA), yet #case(1) is chosen as if #switch is
> 'true.'

Yes, (now that I've gotten some sleep, and looked at the #debug output) I see
that's the case.   I probably won't have an opportunity to run any more tests
until tonight.


Post a reply to this message

From: Bald Eagle
Subject: Re: problem using ORs and strcmp() in #switch/#case
Date: 8 Nov 2017 06:30:00
Message: <web.5a02ea6a1346e9e05cafe28e0@news.povray.org>
"Kenneth" <kdw### [at] gmailcom> wrote:

> #switch(0)
> #case(strcmp(IMG_TYPE,AA))

This should work, as strcmp(IMG_TYPE,AA) _IS_ 0.


> #switch(0)
> #case(strcmp(IMG_TYPE,AA)=0)
>
> I ask because the latter doesn't work--no error message of any kind is created,
> but it falls through to the #else clause, even though strcmp(IMG_TYPE,AA) is a
> 'match' between IMG_TYPE and AA.

Which means that it evaluates to TRUE, or 1, which is NOT 0.

Stop thinking in terms of conditional Boolean word results, and think in 0 or 1.

#if (strcmp(IMG_TYPE,AA)=0)
would give a Boolean result of 1.


I think you're stuck thinking about #switch() and #case() as some sort of
semi-Boolean operator, when it's more of a "pick this value from the following
list" function.  Maybe if you think about the whole block like an array [n] and
the #case statements are picking a specific array item (sort of).

{pseudocode}
#if (Case = n)
      #local Return = Array [n]
#end

and

#if (Range > Low & Range < High)
      #local Return = Array [some appropriate n]
#end


Post a reply to this message

From: clipka
Subject: Re: problem using ORs and strcmp() in #switch/#case
Date: 8 Nov 2017 07:53:52
Message: <5a02fe60$1@news.povray.org>
Am 08.11.2017 um 05:40 schrieb Kenneth:

> I didn't know that using #cases without #breaks was possible :-O  Thanks! That's
> the construction I will probably use; it's nice and elegant. In fact, so
> interesting that a note in the documentation about it would be justified ;-)

It's hinted at very briefly in the v3.7 docs.

> BTW, I almost never use #switch(true) in my scenes, usually just #switch(1) or
> #switch(0)-- believing that they are the 'logical equivalents' of true/false,
> not just the 'number values' 1 and 0. It has always worked for me, but is my
> assumption valid, in light of all that's been said?

`#switch(0)` and `#switch(1)` are perfectly equivalent to
`#switch(false)` and `#switch(true)` respectively, but for code clarity
I would recommend the former when you're dealing with actual numbers
(such as the return value of `strcmp()`), and the latter when you're
dealing with logical expressions (such as the result of the `=` operator).


> Another question, just to clarify something: Is there a difference between the
> following two examples? (I don't actually code the latter way-- it may not even
> be appropriate-- but I've seen various types of non-strcmp() constructions in
> the newsgroups that look similar)...
> 
> #switch(0)
> #case(strcmp(IMG_TYPE,AA))
> 
> and
> 
> #switch(0)
> #case(strcmp(IMG_TYPE,AA)=0)

Yes, absolutely!
If IMG_TYPE is equal to AA, then `strcmp(IMG_TYPE,AA)` will yield 0.
Comparing that result with zero will yield true, i.e. some non-zero number.

So with IMG_TYPE=AA, the first case would resolve to:

    #switch(0)
    #case(0) // representing `zero difference`
      // (we'll enter here, because 0 = 0)

while the second case would resolve to:

    #switch(0)
    #case(1) // representing `true`
      // (we'll NOT enter here, because 0 <> 1)

> I ask because the latter doesn't work--no error message of any kind is created,
> but it falls through to the #else clause, even though strcmp(IMG_TYPE,AA) is a
> 'match' between IMG_TYPE and AA.

The latter case would generate an error or at least a warning in most
contemporary languages, as it is now considered good practice to clearly
distinguish between boolean an numeric values. Even in C, where use of
`int` for boolean values has a long-standing tradition, a dedicated
boolean type has been added by now.

However, POV-Ray's rusty SDL is particularly poor at distinguishing
between values representing entirely different things (another example
being colours vs. vectors), so it can't warn you that you might have a
problem there.


Post a reply to this message

From: clipka
Subject: Re: problem using ORs and strcmp() in #switch/#case
Date: 8 Nov 2017 07:58:22
Message: <5a02ff6e$1@news.povray.org>
Am 08.11.2017 um 12:28 schrieb Bald Eagle:

> I think you're stuck thinking about #switch() and #case() as some sort of
> semi-Boolean operator, when it's more of a "pick this value from the following
> list" function.  Maybe if you think about the whole block like an array [n] and
> the #case statements are picking a specific array item (sort of).

I would pick the analogy of a `#if...#elseif...#end` construct:

    #switch(VALUE)
      #case(COMPARE1)
        // branch 1
      #break
      #case(COMPARE2)
        // branch 2
      #break
      ...
      #default
        // branch Z
      #break
    #end

is fully equivalent (presuming all values are numeric) to:

    #if(VALUE=COMPARE1)
      // branch 1
    #elseif(VALUE=COMPARE2)
      // branch 2
    ...
    #else
      // branch Z
    #end


Post a reply to this message

<<< Previous 6 Messages Goto Latest 10 Messages Next 10 Messages >>>

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