Case Var Of band(Var, equate) - is this legal?

Case Var
Of Band(var,bitmaskequate1)
! Do something
Of Band(var,bitmaskequate2)
! Do something else
Else
! Go home
End

So the docs say for Case
Of expression
Expression is a numeric, string constant or expression.

In the docs for If it says
Logical expression which is a variable, procedure, or expression which evaulates a condition.

So using
Case var
Of band(var,bitmaskequate)

It fails in the case but works in an IF statement.

So is band(var,bitmaskequate) not legal in a case OF statement?

I add bitmask equates using bor() and remove them using bxor().

I dont get a compiler telling me no.

So is an OF band(var,bitmaskequate) legal?

Case is supposed to be faster than an IF which is why I wanted to use it, but no big deal if I cant.

I suppose technically band() is evaluating a condition but without a compiler error Ive got doubt.
Tia

You might have better results with something like this (assuming the bits in those masks don’t clash). This is how I’d do it:

   CASE BAND(Var, bitmaskequate1 + bitmaskequate2)
   OF bitmaskequate1
   OF bitmaskequate2
   OF bitmaskequate1 + bitmaskequate2 ! Both masks are in there
   ELSE
   END

If the bits clash, you can use

  CASE(BAND(Var, BOR(bitmaskequate1,bitmaskequate2))

I’ll see how that goes, theres a few bitmask equates, but probably no more than 8-12 bitmask equates used in an if statement code block at a time.

Theres no clashes so no need for the bor route.

It wouldnt have occurred to me to addup all the bitmask equate options in the subsection/range Im checking but thinking about it, it works and its actually eloquent.

The problem is, you never know quite how this code is being processed behind the scenes. Copyright prohibits me from using ghidra to look. Law never focuses on the negatives it creates.

Edit.

I think this could work well namely because I have bitmask equates which can trap all options in a section/range so Id only have to use that “catch all” equate instead of bor()'ing various equates together on the Case() line, testing even the widest ultra wide monitors!

Ie
StrPos:trimleft equate(001b)
StrPos:trimright equate(010b)
StrPos:trimboth equate(011b)

Case band(var, StrPos:trimboth)
Of StrPos:trimboth
! Some code1
Of StrPos:trimleft
! Some code2
Of StrPos:trimright
! Some code3
Else
!unhandled
End

Or

StrPos:lefttorightprocessing equate(001b)
StrPos:righttoleftprocessing equate(010b)
StrPos:errorrightleftleftright equate(011b)

Case band(var,strpos:errorrightleftleftright)
Of strpos:lefttorightprocessing
! Do L2R code
Of strpos:righttoleftprocessing
! Do R2L code
Of strpos:errorrightleftleftright
! Var = bxor(var,strpos:errorrightleftleftright)
! Var = bor(var,strpos:rightoleftprocessing)
Else
! Logic fail
End

The layout is nice, without having to have shed loads of bitmask equates in the Case() line of code.

Remember, you can always do the algorithm in C and call it from a function in Clarion from the same IDE.

Yeah same with assembler and modula 2, I prefer clarion.

#pragma call(inline => on |off)

Plus using the case instead of the if statements reduces the opportunities to make erronous code. Its very easy to mess up complex if statements.

So this isnt working how I thought it worked in an earlier simpler test.

The above example works but where there are lots of bitmasks it doesnt.

So for safety sake, Im going back to the IF statements. More coding, didnt look nice to look at codewise but it worked.

Nothing wrong with a bunch of IFs :slight_smile:

But for a small subset of bits, sometimes CASE is nice and clean.

Not sure what issues you were running into, but I’m guessing it’s clashing bits getting added up.

It definitely would not work correctly if the mask was not the value that your CASE structure would expect or if something was not correct in the CASE structure.

If you use ELSIF, the result is not that different from your original code, even one line shorter. You can add ELSIFs just like adding OFs.

If Band(var,bitmaskequate1)
! Do something
Elsif Band(var,bitmaskequate2)
! Do something else
Else
! Go home
End
Case Var
Of Band(var,bitmaskequate1)
! Do something
Of Band(var,bitmaskequate2)
! Do something else
Else
! Go home
End

I thought the case band(var,equates) where equates wasnt all the bitmask equates, just a range of bit masks and then testing for bitmasks in that range of bitmasks would work, but it doesnt.

Im going back to the ifs because if the band(var,bitmaskequate) test true, as long as its in the right order of the IF/elsif statement it appears to work so far.

I only started looking at case because the if statements stopped working.

Its one thing after another, can never get any program finished.

I really do question the circumstances of how I got in to clarion, if I could turn back time I wouldnt use it today. Got my dodgy mother to thank for that!

Yeah, your data has to be pretty rigidly organized, as do the masks that you pass, in order for CASE to be practical for this.

But remember that these bitwise functions (Clarion or otherwise) are pretty much like any other math operator. There’s no magic about them “working” or “not working”, whether used in an IF or CASE. The things that change about them are our expectations and assumptions. :slight_smile:

Additionally, with regard to your comments about BAND(), if your mask that you’re passing utilizes more than one bit, you have to watch out for what you call “TRUE” when you say that things “test true”.

BAND just returns a value. You, as a programmer have to decide whether a non-zero return value is TRUE or not. The return value of BAND() is just the matching bits, but there could be bits that were not included.

e.g.

MyMask  EQUATE(03H) ! 011b
MyValue LONG
  CODE
  MyValue = 01H

  ! Sometimes this is what you want:
  IF BAND(MyValue,MyMask) ! This returns "not false" with our example data
     ! Any matching bits
  END

 ! But other times, you might have to get more specific:
  IF BAND(MyValue,MyMask) = MyMask ! This returns FALSE with the example data
     ! All matching bits
  END

Whether the language that you’re using is Clarion or something else, bits is pretty much bits.

1 Like

Ive got to the bottom of it. Band isnt working properly, but I dont know how to proceed.

So tldr
Band is returning a value for an equate that hasnt been placed in the bitmask var.

Consequently Im getting different values returned by band.

Eg
Eq1 equate(0001b)
Eq2 equate(0010b)
Eq3 equate(0011b)

Bm long
Rv long

Bm = bor(bm,Eq1)
Rv = band(bm,eq2)
Rv = band(bm,eq3)
Rv contains the value for Eq1 when Im expecting it to be zero.

Bor and bxor are adding and subtracting nicely as expected, bshift is working as expected
Eg I have 21 bitmasks so I shift them -21 to see if there is any value using the 22nd or more bits as another check, but I simply was not expecting band to return a value only a zero.

This is also why I thought I could use case band(bm,eq3) as a sort of range check.

Edit.
The quick fix is to qualify the if statement better because that only wants a zero as false and all other values positive or negative as a true, so
If band(bm,eq3) = eq3
Would fix the problem but Im thinking something like
bEqual procedure(**? var, ? bitmask),byte
Code
Return choose((band(var,bitmask) = bitmask),1,0)

Would avoid future mistakes as an off the top of my head example.

Edit2
So the bequal example works perfectly as expected.

So simple, and whilst it can be used in a case statement as its returning true or false there is no point when looking at how much more code has to be written compared to an if statement.

If bequal(var,bitmask)
! True
Else
! False
End

Case bequal(var,bitmask)
Of bequal(var,bitmask)
Orof true
! Do something
Of not bequal(var,bitmask)
Orof false
! Do something else
Else
! Month of Sundays
End

That code example for band in the help docs, it isnt the best and band isnt but is the best function for testing for bitmasks provided they have an = requiredbitmask to qualify it with.

I am glad you found a satisfactory solution, but just to clarify: There is nothing wrong with BAND(). It works as defined.
Any issues I ever had with it were of my own doing and/or ignorance.

Hi Richard

I am with Jeff on this - I have never had a problem with band().

Let’s look at your example above.

Bm = bor(bm,Eq1)

as Bm has been initialised to zero, here you could have simply said

Bm = Eq1

or even just

Bm = 1

after your next statement

Rv = band(bm,eq2)

Rv will be 0 as you are BANDing 01b with 10b and no matching bits are on

then in your next statement, you overwrite the Rv value

Rv = band(bm,eq3)

where bm is 1 (from the first statement) so you are saying band(01b, 11b) and so there is one matching bit on which is 1.

Rv contains the value for Eq1 when Im expecting it to be zero.

you should be expecting it to be 1 which is Eq1 so perhaps consider “adjusting your expectations” :grinning:

You sometimes see “Expectation is the root of all heartache” incorrectly attributed to William Shakespeare. I have no idea who actually said it…

2 Likes

I just looked at the code example, and reading the docs I can see band is going to return a value for each matching bit. But I was expecting it to return a true or false having just looked at the code example and not the txt.

Ive only just managed to find the setting in win11 to stop the bloody screen dimming which takes place when I alt tab between apps.
Its called system > display > brightness - change brightness based on content - off, always, on battery.

It was set to always and I now have it set to off. I also think MS sell this data to insurance companies!

Point being Im working on a not good display and its hard to read. I didnt use to be dyslexic but the way the txt jumps around now, I think I would pass for being dyslexic!

I also struggle to see text in the debugger now because I have become colour blind and didnt use to be.

And if you think social healthcare aka the NHS is wonderful, forget it they wont let me have the treatments that work and they couldnt diagnose themselves out of a paperbag. Wish I went private years ago, but I bought the lies of the state.

I can see why you would expect that. I’m guessing that most usages of BAND use it as a binary statement. If you’re just talking one “true” bit in your mask, that works fine.

Knowing where something wouldn’t work fine is the thing we never know about in time to save ourselves from getting some lumps. Looks like your wrapper function will get you what you need and you’re now a BAND() expert. :slight_smile:

Hope you can sort out the eye/screen issues.

ah yes I can see the problem - and an easy misunderstanding to make given the help example has code like:

IF BAND(RateType,Female)| !If female
AND BAND(RateType,Over25) ! and over 25

if you wanted true/false you could perhaps wrap it in choose() :

choose(band(bm,eq2)) ! will return 1 or 0 (true or false)

yes me too.

Its not the best, but if you want to get on and dont read the txt, it will mislead you. Its highly intellectual when you start looking at the bugs and lack of return values. It makes me think one is only allowed to reach so high.

Building this strpos procedure to extend the strpos functionality has shown me that there are right ways and wrongs to write apis.

OTOH, sometimes matching ANY of the bits in the mask that you pass could be the answer you want.

I have an app where I use a checkbox to set a “strict” setting. This requires the exact match to the mask. Without that setting, you can match any of the bits.

Both ways are desirable behaviors.

Yeah, and maybe its time to find some other job before anymore of my life stolen.