Re: Casting int <--> double and signs

new topic     » goto parent     » topic index » view thread      » older message » newer message

Thanks for the answers, Matt.

I knew I had probably introduced some bad casts, when my intention was to either remove redundant casts (casting NewDouble to an object when it already returns an object and the like) and fix casts where the result could be undefined (casting a double to an int or uint without determining sign and over/underflow).

I went a little overboard and got lost in the weeds. I didn't even realize that t_rand.e was causing a bus error/segfault on 32-bit because that didn't show up in test-report.html when I ran 'make test'. I assumed it was only failing on 64-bit.

mattlewis said...

I think this is a problem with the manual. There was a lot of discussion about this, and the decision was made to return unsigned values.

I think I want to revisit this. I'll check the sourceforge dev list archives to see if I can find the previous discussion, but my argument would be this: If the inputs are signed, then the outputs should be, otherwise they should be unsigned, with the exception of not_bits which should always return a signed value.

This is for consistency. We can either have not_bits(not_bits(-1)) = -1 or we can have not_bits(not_bits(#FFFFFFFF)) = #FFFFFFFF (32-bits used for brevity) because #FFFFFFFF != -1. I'll think about it some more and see if we can have both, I really think that we can.

On the plus side if it returns signed, that can be a way of converting an unsigned hex constant to a signed integer.

mattlewis said...

When using a pointer (in the back end or translated) it will be cast to a pointer type, and it's interpreted as unsigned. I suppose we could return it as a signed value, which on 32-bits would keep more pointers as integers, but this seems like a bad idea.

Maybe I'm misunderstanding, but all pointers in the back end are signed types (object is typedef'd to intptr_t) so that it can be determined if it is an integer, atom, or sequence.

I agree that it should be returned to the user as an unsigned pointer; but that users should be allowed to use signed pointers as arguments if they want. That's what I meant -- we should assume that addresses are uints for output back to the user, but we should accept either uints or signed ints FROM the user. Maybe they got a signed value from an expression? I don't know.

I guess what I mean is that the policy should be that the user shouldn't have to worry about signed vs. unsigned unless they want to do so.

mattlewis said...

We have signed and unsigned versions of peek. Pokes don't matter. What sort of bounds checking? Something beyond what std/safe.e does?

I'm not sure what safe.e does. I'll have to go look. What happens if you do

poke2u(addr, -16380) 
poke2s(addr, 60956) 

Do you get an error, or does it convert signed<-->unsigned silently?

mattlewis said...

It's to prevent overflow. It's been a while, but I think the problem is that if it's greater than that, then the next digit (if one exists) will cause the value to be stored as floating point. If it was the last digit, then it doesn't really matter, but if there are more, this keeps everything OK. We resume checking digits below.

Thanks, that actually makes sense thinking about it. Was 'i' originally declared as an integer? Because it is declared an atom now.

As I think about this, does it make more sense to be one of

i < TMAXINT/16 -- leave room for one more digit 
-- equivalent to i <= TMAXINT/32?  
--snip-- 
if i>= TMAXINT then 
    is_int = FALSE 

Or is that still subject to overflow?

Regardless, it seems to work as-is.

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu