PB 4.20 (beta 2) expression evaluation / casting issue

Just starting out? Need help? Post your questions and find answers here.
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

PB 4.20 (beta 2) expression evaluation / casting issue

Post by dell_jockey »

Consider this code:

Code: Select all

_Resolution_.w = 2000       
dummyFloat.f   = 1234.5678

Dim Table.f(_Resolution_ - 1)

For n = 0 To (_Resolution_ - 1)                            ; populate table.
  Table(n) = dummyFloat.f / ( (_Resolution_.w >> 1) * n )  
Next  
an array of floats should be filled with values, that in part depend on an integer/word value that needs to be divided by two. For that division I intended to use the >> operator.

At that point I get the error:

Code: Select all

"Can't use any of the following operands with floats: <<, >>, &, |, !, %"
To me this means that _Resolution_.w gets cast to a float, before it is right shifted one place, even when this right shift operation is contained within its own brackets.

Shouldn't PureBasic evaluate everything within brackets first, BEFORE casting the result to float?

If this issue really is an error, please let me know so that I can re-file under bugs.
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

I think this has been a facet of PB right from the outset as I remember coming across something like this before. Because the rhs of your expression involves a float, everything is promoted to this type prior to the expression being evaluated.

The same would be true of a calculation involving bytes, words and longs; all the variables in question would be promoted to longs in this case prior to evaluation.

Unless I'm mistaken (which is more than possible!) c++ would do something similar.

Of course, the solution is to simply break your expression down etc.
I may look like a mule, but I'm not a complete ass.
Dare
Addict
Addict
Posts: 1965
Joined: Mon May 29, 2006 1:01 am
Location: Outback

Re: PB 4.20 (beta 2) expression evaluation / casting issue

Post by Dare »

dell_jockey wrote:Shouldn't PureBasic evaluate everything within brackets first, BEFORE casting the result to float?
I think it should. I rely on brackets getting precedence, and for casting being done only at the stage when required. So far I have been lucky. Or maybe it just hasn't made a difference to end result in my expressions.

Actually 4.1 throws that error as well.

1 vote for bug (or at least an imPurity). But hang in for others to comment. :)
Dare2 cut down to size
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Ah, if we're voting then I vote for no bug - its just the way it is, the way I imagine a lot of compilers operate. It certainly makes the compiler somewhat simpler.

I imagine that at some point Fred made a conscious decision to proceed in this way as I find it hard to believe that it could be an accident. From that point of view then I have to say that it is likely by design rather than a bug resulting from an oversight. :)
I may look like a mule, but I'm not a complete ass.
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Post by dell_jockey »

srod wrote: Unless I'm mistaken (which is more than possible!) c++ would do something similar.
in C / C++ anything inside brackets or curly braces is evaluated first. Only after evaluating stuff inside brackets a cast takes place. Curly braces are even used to define a scope, i.e. variables defined within curly braces are only visible / exist within those curly braces.
Last edited by dell_jockey on Fri Feb 15, 2008 11:35 am, edited 1 time in total.
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Re: PB 4.20 (beta 2) expression evaluation / casting issue

Post by dell_jockey »

Dare wrote:I think it should. I rely on brackets getting precedence, and for casting being done only at the stage when required. So far I have been lucky. Or maybe it just hasn't made a difference to end result in my expressions.
at least I got an error message....

A PureBasic 'inPurity', a nice find :)
Last edited by dell_jockey on Fri Feb 15, 2008 1:49 pm, edited 1 time in total.
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

I stand corrected on that one. :)

Actually, when I sat back to think about that rash statement of mine I decided that c++ probably did only promote variables when absolutely necessary! Oh well! I still think though that Fred has made a conscious decision to promote all variables at the outset of an expression evaluation etc.
I may look like a mule, but I'm not a complete ass.
#NULL
Addict
Addict
Posts: 1499
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Post by #NULL »

we just had that in german forum

Code: Select all

distance.l = 10

If distance < (64 * 0.5)
    Debug "less"
Else
    Debug "greater"
EndIf 
'0.5' is casted to integer '0' before multiplication, because of 'distance' being an integer.
it's a pity, but as srod said, that's how it works in PB, so once you know it you can just be more carefull.

other way round it works

Code: Select all

If (64 * 0.5) > distance
..or you can use Int() for the braced part..
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Actually #NULL, there is no multiplication being performed at runtime here; the compiler is converting 64 * 0.5 to 0 directly during compilation.

So we have two issues here; the compiler promoting / casting literal values during compilation and promoting / casting variables during runtime etc. :)
I may look like a mule, but I'm not a complete ass.
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Post by dell_jockey »

#NULL wrote: other way round it works

Code: Select all

If (64 * 0.5) > distance
..or you can use Int() for the braced part..
now, that does make sense, doesn't it? :cry: alas, one more "inPurity" to keep track of...
I'm starting to befriend 'manual typecasting' à la C again. At least then the compiler doesn't do anything unexpected.
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
ZeHa
User
User
Posts: 38
Joined: Sun Apr 24, 2005 11:39 pm

Post by ZeHa »

srod wrote:Actually #NULL, there is no multiplication being performed at runtime here; the compiler is converting 64 * 0.5 to 0 directly during compilation.
Yeah, I thought that too. But unfortunately, it isn't...
The code with the "distance" variable is from my current project, and the 64 was a constant called #TILE_HEIGHT. I also expected the multiplication to happen right at compile time and not at run time - but it really seems to happen at run time, 0.5 gets casted to long and then yields 0.

Now, if you change distance.l to distance.f, it suddenly works!
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

If you look at the generated assembly code you can see that the compiler has changed 64 * 0.5 to 0; it is in the XOR EAX, EAX statement.

Change to 64 * 1.5 and you see explicitly (in the assembly code) that the compiler inserts 96 in it's place.
Now, if you change distance.l to distance.f, it suddenly works!
Yes it would do, everything is then promoted to floats and 64*0.5 will be replaced by 32 by the compiler (not at runtime -confimed by looking at the asm).
I may look like a mule, but I'm not a complete ass.
ZeHa
User
User
Posts: 38
Joined: Sun Apr 24, 2005 11:39 pm

Post by ZeHa »

srod wrote:Change to 64 * 1.5 and you see explicitly (in the assembly code) that the compiler inserts 96 in it's place.
But isn't that crazy?!

When I'm using 64 * 0.5 and it gets casted to longs, then of course I understand that 0.5 becomes 0 and 64 * 0 is of course also 0.

When I'm using 64 * 1.5 and it gets casted to longs, I'd expect that 1.5 becomes 1 and the compiler should replace it with 64, not with 96!


And, of course, I expect the right hand side of a comparison to be evaluated BEFORE the left hand side has got to do anything with it. So, I'd expect the 64 * 0.5 to happen like it should (to become 32 at compile time), and after that, it can safely be compared with the left hand side and also be casted. But it shouldn't be casted until it has been fully evaluated.
That's the initial problem, but that weird 0.5/1.5 stuff above seems even more problematic...
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Aye, I missed the significance of that.

Yes, that is very strange indeed. I've just rechecked and, in the case of longs, the compiler does indeed regard 64*0.5 as 0 whilst 64*1.5 is changed to 96.

Very strange. An inconsistency like this must go down as a bug.


@dell_jockey : no arguments with this aspect! :) Do you want to make a bug report or shall I?
I may look like a mule, but I'm not a complete ass.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

wow.... this could be bad. i wonder at the # of bugs i've tried to find that were caused by this...
Post Reply