Author Topic: _SHR bug with sign bit of _UNSIGNED _INTEGER64  (Read 4578 times)

0 Members and 1 Guest are viewing this topic.

Offline eric

  • Newbie
  • Posts: 3
    • View Profile
_SHR bug with sign bit of _UNSIGNED _INTEGER64
« on: December 03, 2019, 06:20:30 pm »
Hello,

I use qb64 to test some algorithms on integers when i got a strange garbage.

So, i try :

Code: QB64: [Select]
  1.  
  2. n = &H0100000000000000
  3.  
  4. PRINT , HEX$(n)
  5. n = _SHL(n, 7)     'shift 1 to sign bit left most
  6. PRINT , HEX$(n)
  7. n = _SHR(n, 7)     'revert to first position
  8. PRINT , HEX$(n)
  9.  
  10. m~&& = &H0100000000000000
  11. PRINT , HEX$(m~&&)
  12. m~&& = _SHL(m~&&, 7)
  13. PRINT , HEX$(m~&&)
  14. m~&& = _SHR(m~&&, 7)
  15. PRINT , HEX$(m~&&)
  16.  

both display result as :

     100000000000000
     8000000000000000
     FF00000000000000


I think _SHR is not shifting but expanding the "sign" bit to the right.

The last print is the negative of the first.

Is it a solution ?

Thanks.


Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Re: _SHR bug with sign bit of _UNSIGNED _INTEGER64
« Reply #1 on: December 03, 2019, 07:30:03 pm »
Absolute correct behavior here, imagine you would give any negative number as input for _SHR. As _SHR is basically a division, the sign of the divident must be preserved eg. -2/2 (_SHR(-2,1)) is -1, hence the sign bit must stay in place and extended to the right.

The fact that you first move a bit from a regular data position into the sign position doesn't matter here, the result is a negative number which you then pass on to _SHR.

For prove of this just use the windows calculator, switch to programmers mode and do the operations there, you'll see its the same.
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline Richard Frost

  • Seasoned Forum Regular
  • Posts: 316
  • Needle nardle noo. - Peter Sellers
    • View Profile
Re: _SHR bug with sign bit of _UNSIGNED _INTEGER64
« Reply #2 on: December 04, 2019, 02:39:58 am »
I'm confused. 

What is the point of an _UNSIGNED variable if operations recognize the leftmost bit as a sign?

It works better if you plug it in.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: _SHR bug with sign bit of _UNSIGNED _INTEGER64
« Reply #3 on: December 04, 2019, 03:07:33 am »
I'm confused. 

What is the point of an _UNSIGNED variable if operations recognize the leftmost bit as a sign?

All functions have limits on their return values, according to their return type. In this case, it’s a SIGNED _INTEGER64.

Now, why was a signed type chosen over an unsigned one, you ask?

Let’s look at a few values:

11111111 — as a signed byte, this represents the value for -1.
01111111 — Now, if we just shift it right once, it suddenly becomes +128??  <— This is basically what happens if we just shift everything, with no regard to the sign bit being special.

Most people think of a bit shift as basically being a math operation of times two, or divide by two — not a case of times 128, negated...

So, to preserve that “shift by a power of two” mechanic, we hold that first bit in reserve for negative values.

11111111 <— Again, this represents -1, in a signed byte.
10111111 <— Now, we shifted our bit once, and we have -2... 

You might pass the function an _UNSIGNED variable, but it’s processing and working with the signed version.  Think of it as:

FUNCTION foo (foo2 AS _INTEGER64)

Now, we can pass foo an integer, a single, a float, or an unsigned INTEGER64, but what’s it actually going to process it as, for us, internally?   

(foo2 AS _INTEGER64) <— this says it’s accepting and working with a signed INTEGER64, no matter what we send it...
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: _SHR bug with sign bit of _UNSIGNED _INTEGER64
« Reply #4 on: December 04, 2019, 05:04:58 am »
I agree with Richard Frost, the output should be
100000000000000
8000000000000000
100000000000000
here's C code that outputs the above
Code: C: [Select]
  1. #include <stdio.h>
  2. int main(void)
  3. {
  4.         unsigned long long int n;
  5.         n=0x0100000000000000;
  6.         printf("%llx\n",n);
  7.         n=n<<7;
  8.         printf("%llx\n",n);
  9.         n=n>>7;
  10.         printf("%llx\n",n);
  11.         return 0;
  12. }
  13.  
« Last Edit: December 04, 2019, 06:30:33 am by jack »

Offline eric

  • Newbie
  • Posts: 3
    • View Profile
Re: _SHR bug with sign bit of _UNSIGNED _INTEGER64
« Reply #5 on: December 04, 2019, 11:22:11 am »
Thanks for yours replies.

I got trouble because of the name _SHR that is like the assembly mnemonic :
Quote
shr
that means unsigned shift right without matter of a sign bit.

The qb64 _SHL function works as instruction :
Quote
sar

that  shifts right too but preserving the sign bit

Left shifts, sal and shl, exist but are the same.

Short example in assembly (debug screen copy in attachment):

mov ax, 8000h
mov dx, ax
mov cl, 3
shr ax, cl
sar dx, cl        ;  _SHR(&h8000, 3)

input ax  : 1000000000000000     &h8000
output ax: 0001000000000000     &h1000
output dx: 1111000000000000     &hF000       _SHR(&h8000, 3)



Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: _SHR bug with sign bit of _UNSIGNED _INTEGER64
« Reply #6 on: December 04, 2019, 12:01:48 pm »
If you guys are curious what/how QB64 is handling this command, here's what we're processing under the hood:

Code: C++: [Select]
  1. //bit-shifting
  2. inline int64 func__shl(int64 a1,int b1)
  3. {return a1<<b1;}
  4.  
  5. inline int64 func__shr(int64 a1,int b1)
  6. {return a1>>b1;}

Functions don't get much simpler than that, and it's not a whole lot of room to introduce bugs into things.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: _SHR bug with sign bit of _UNSIGNED _INTEGER64
« Reply #7 on: December 04, 2019, 12:05:26 pm »
@SMcNeill
the function you posted is for signed integers, it's not what eric needs

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: _SHR bug with sign bit of _UNSIGNED _INTEGER64
« Reply #8 on: December 04, 2019, 12:22:38 pm »
@SMcNeill
the function you posted is for signed integers, it's not what eric needs

It's the only one we have.  SHR and SHL only support signed integers, at the moment.  If someone wants to write us a nice set of code which toggles between sign/unsigned, I'll be happy to push your changes into the repo for us. ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Richard Frost

  • Seasoned Forum Regular
  • Posts: 316
  • Needle nardle noo. - Peter Sellers
    • View Profile
Re: _SHR bug with sign bit of _UNSIGNED _INTEGER64
« Reply #9 on: December 04, 2019, 04:04:29 pm »
I propose that the functions _SHL and _SHR also take Bitcoin, with
_SHL doubling the money, and _SHR generating a GPF, or causing Cuba
to sink, whichever is easier.

O-tay, so it's a minor limitation, not a bug.

It works better if you plug it in.

Offline eric

  • Newbie
  • Posts: 3
    • View Profile
Re: _SHR bug with sign bit of _UNSIGNED _INTEGER64
« Reply #10 on: December 05, 2019, 03:34:28 am »
Finally i find a workaround based on http://qb64.org/wiki/C_Libraries#Bit_Shifting :

Modified C include file in qb64 dir :
Code: C: [Select]
  1.  //ushift.h
  2.  
  3. uint64 uShiftR(uint64 Value, unsigned ShiftValue)
  4. {
  5. return(Value >> ShiftValue);
  6.  
  7. }
  8. uint64 uShiftL(uint64 Value, unsigned ShiftValue)
  9. {
  10. return(Value << ShiftValue);
  11. }
Basic declare and a piece of code that works :
Code: QB64: [Select]
  1. 'ushift.bas
  2. DECLARE LIBRARY "ushift" 'use first name of .h file
  3.     FUNCTION uShiftR~&& (BYVAL Value AS _UNSIGNED _INTEGER64, BYVAL ShiftValue AS _UNSIGNED LONG)
  4.     FUNCTION uShiftL~&& (BYVAL Value AS _UNSIGNED _INTEGER64, BYVAL ShiftValue AS _UNSIGNED LONG)
  5.  
  6. n = &H1000000000000000
  7.  
  8. PRINT , HEX$(n)
  9. n = uShiftL(n, 3)
  10. PRINT , HEX$(n)
  11. n = uShiftR(n, 3)
  12. PRINT , HEX$(n)
  13.  

I had just to modify the types of variables and return value.

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: _SHR bug with sign bit of _UNSIGNED _INTEGER64
« Reply #11 on: December 05, 2019, 10:47:11 am »
I propose that the functions _SHL and _SHR also take Bitcoin, with
_SHL doubling the money, and _SHR generating a GPF, or causing Cuba
to sink, whichever is easier.

O-tay, so it's a minor limitation, not a bug.


no no, _SHR just causes Global Warming! STOP using it!
Granted after becoming radioactive I only have a half-life!