• Dear Cerberus X User!

    As we prepare to transition the forum ownership from Mike to Phil (TripleHead GmbH), we need your explicit consent to transfer your user data in accordance with our amended Terms and Rules in order to be compliant with data protection laws.

    Important: If you accept the amended Terms and Rules, you agree to the transfer of your user data to the future forum owner!

    Please read the new Terms and Rules below, check the box to agree, and click "Accept" to continue enjoying your Cerberus X Forum experience. The deadline for consent is April 5, 2024.

    Do not accept the amended Terms and Rules if you do not wish your personal data to be transferred to the future forum owner!

    Accepting ensures:

    - Continued access to your account with a short break for the actual transfer.

    - Retention of your data under the same terms.

    Without consent:

    - You don't have further access to your forum user account.

    - Your account and personal data will be deleted after April 5, 2024.

    - Public posts remain, but usernames indicating real identity will be anonymized. If you disagree with a fictitious name you have the option to contact us so we can find a name that is acceptable to you.

    We hope to keep you in our community and see you on the forum soon!

    All the best

    Your Cerberus X Team

Snippet Bit logic

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,414
For everyone who deals with bits and got confused about the Shr resemblence like I did as a X64 hobbyist programmer,
this one's for you!

3 demos : Simple shift, logic shift, and signed math using only recursive logic

Hope someone will enjoy this!

Cerberus:
Import mojo2
'
' in C/C++ >> usually means arithmetic shift when used with signed integers (otherwise logical shift).
' in JavaScript >> always means arithmetic shift (>>> being logical shift).
'
    
Function Main()
    New Game
    Return 0
End

Class Game Extends App
 
    Field canvas:Canvas
     Field b:Int
 
    Method OnCreate()
 
        canvas = New Canvas()
        SetSwapInterval 1 ; SetUpdateRate 0
        ' Local b:Int
    
        b = -65535 ' 11111111111111110000000000000001 in 2's complement

        ' DEMO 1 (Arithmetical shift)
        b = b Shr 1 ' Arithmetic shift! (this has nothing to do with the assembly instruction Shr, but Sar. It's just short for Shift right)
        Print b    ' Outputs -32768 which is 11111111111111111000000000000000 in 2's complement
    
        ' DEMO 2 (Logical shift)
        b = b & $7fffffff ' Force logical shift! (by inserting zero on leftmost side)
            Print b    ' Outputs 2147450880 which is 01111111111111111000000000000000 in 2's complement
 
        ' DEMO 3 (Addition and subtraction using only logic)
        Print addsub(10000,-1000) ' Outputs 9000
    
        Return 0
    End

    Method OnUpdate()   
        If KeyHit(KEY_ESCAPE) Then OnClose()
         Return 0
    End

    Method OnRender()
        canvas.Clear
        canvas.Flush
        Return 0
    End

    Function addsub:Int(a:Int,b:Int)
        If b = 0 Then Return a Else Return addsub(a ~ b, (a & b) Shl 1)
    End

End
 
Last edited:
This also meant I could solve the previous problem with the bit-storage, which was misbehaving at highest bits.
The above post explains why. So I re-wrote all the code. This works with all bits and can deal with both two 16-bit numbers inside one int (which is 32-bit). Choose for yourself if you want to store in the int, two -32768 to 32767 numbers, or two 0-65535 numbers.

This demo actually contains two things, first it shows you how to make a simple circular stack, as well as the main thing which is to show you how to put two signed or unsigned numbers into a single int.

This could be to save space, and network traffic for instance. In this version not a single bit goes to waste.


Cerberus:
Strict
 mi
    Global data:Int[65535] ' Set the size of the circular stack (this is just any arbitrary size).
    Global sp:Int = 32768 ' Set the pointer in the middle of the stack.
 
Function Main:Int()

    Local x:Int = 65535
    Local y:Int = 65535

    ' PUSH X,Y -------------------------------
    sp = sp - 1
    data[sp] = ( (x Shl 16) | (y & 65535))
    ' -----------------------------------------
 
    ' POP X,Y ---------------------------------------------------------------------
    Local m:Int = data[sp] ; sp = sp + 1
    x = (m Shr 16) & 65535 ; y = m & 65535        ' Unsigned 16-bit (0 to 65535)
     ' x = (m Shr 16) ; y = m Shl 16 ; y=y Shr 16    ' Signed 16-bit (-32768 To 32767)
    ' ------------------------------------------------------------------------------

    Print x
    Print y

    Return 0 
End
 
Last edited:
Here's how to list all bits, and how to count all bits of a signed Int.
This might come handy for debugging bit-related things!

Cerberus:
Strict

Function Main:Int()

    x = 128 + 64 + 2 ' 3 1-bits
    ' x = -255 ' 25 1-bits (10000000 11111111 11111111 11111111)
    ' x= -1 ' should be 11111111 11111111 11111111 11111111
    ' x = 1 ' should be 00000000 00000000 00000000 00000001
    ' x = x - 1 ; x = ~ x

    ' List all bits
 Local all:String = ""
     For Local temp:Int = 31 To 0 Step -1
         If x & Pow(2,temp) Then all=all+"1" Else all=all+"0"
          If temp Mod 8 = 0 Then all=all+" "
     Next
     Print all

    ' Count number of 1-bits
    Local n:Int = x
    Local count:Int = 0
    Local mask:Int = 1
    For Local temp:Int = 0 To 31
        If ( (mask & x) = mask) Then count = count + 1
        mask = mask Shl 1
    Next
 
    Print count
  
    Return 0 
End
 
Last edited:
EDIT: Look in the next post for the fully working latest code, this post and previous posts are left a curiosity regarding the bug in the old version.

I want to mention that even if the bitcounter handles everything the bit PRINTER fails on one single number.

That number is the biggest positive number for an INT inside Cerberus-X, 214748364.
The counter will claim the correct numbers of 1's (31, as the highest is a zero).

The bit-PRINTER though, will give you 32' 1's despite the highest bit should print as a zero of course.
Tried to debug this night but wo success, so I'll mention it here.

So to get the feeling of the bug, take these examples;
x = %10111111111111111111111111111111
x = %00111111111111111111111111111111
x = %11111111111111111111111111111111

They will give you correct result in every way, as will every other value.

Now to the isolated value that will constitute the bug :
x = %01111111111111111111111111111111
This value will only show up correctly in the bit counter (should be 31), it does NOT show up correctly in the bit PRINTOUT, it will instead give you all 1's.

You can check for yourself using this
Print x Shr 31 ' This prints 1 if first bit is 1 (this will show 0 for %01111111111111111111111111111111)

So there's just a difficult bug in the Bit-PRINTOUT loop for this value. The strange thing is that it works in all other cases.
 
Last edited:
Rewrote the code to fix the bug (if someone knew why the bug appeared in the old I'm interested)

Code:
        Strict

Function Main:Int()
Local x:Int
x = 128 + 64 + 2 ' 3 1-bits
' x = -255 ' 25 1's (11111111 11111111 111111111 00000001)
' x= -1 ' should be 11111111 11111111 11111111 11111111
' x = 1 ' should be 00000000 00000000 00000000 00000001
' x = x - 1 ; x = ~ x

    ' List all bits (Fully working now)
     Local all:String = ""
     For Local temp:Int = 31 To 0 Step -1
        If (x Shr temp) & 1 Then all=all+"1" Else all=all+"0"
        If temp Mod 8 = 0 Then all=all+" "
     Next
     Print all

' Count number of 1-bits
Local n:Int = x
Local count:Int = 0
Local mask:Int = 1
For Local temp:Int = 0 To 31
If ( (mask & x) = mask) Then count = count + 1
mask = mask Shl 1
Next
 
    Print count
 
Return 0
End
 
Last edited:
If you prefer other bases while working with bits you can use this, insert the parameters base as 16 to get hex, 2 for binary, 10 for decimal (meaning no conversion) etc.

EDIT the dec2any has a slight bug so don't use this one just yet. WIP

Code:
Method dec2any:String(value:Int,base:Int)
        Local m:String=""
        Repeat
            Local rem:Int = value Mod base
            value =  value / base
            m = Mid("0123456789abcdefghijklmnopqrstuvwxyz",rem + 1,1) + m
        Until value = 0
        m="0"+m ' this formats hexadecimal when only using one digits so you might wanna change this line
        Return m
    End
 
Last edited:
Got all the bits down now.
You've got total assembly-level control of every tiny bit. Now the fun starts :coffee:
 
Interesting fact to know about cx

You can use do this

Code:
Local x:Int
x = %11111111111111111111111111111111
x = $ffffffff
x = 4294967295 ' unsigned max

..and these will all output the correct bits into x!

Of course the behavior of < > =< => will behave like it is signed so negative numbers needs special treatment, but the contents is absolutely correct.

I just wanted to tell the fact that you can get any positive or negative range of values (Dec Hex or Bin) will get correctly interpreted at compile-time, there's no limit. That's nice news!

EDIT in HTML5 you get 53-bit for free as there is no other number.
Btw for those who wonders why people always say both 64-bit and 53-bit when they talk about JS.. which one is it?
it's a std 64-bit float, out of which you can create 53-bits integers wo any errors or gaps (it's actually' 52 bits and 1 bit exponent that works as the last additional bit so they add up to 53 bits). Just look at it as a simple 53 bit signed integer.

I'm not sure yet how to access it but at least Pow and/or Mod will benefit from these additional bits in HTML5 if I understood my testings correctly.
 
Last edited:
Back
Top Bottom