Τετάρτη 8 Ιουλίου 2026

Shift 64bit (using 32bit shift)

This is a module to demostrate the bit shift for 64bit using 32bit shifts (and rotate). The HiLow structure define a union of a long long (64bit) unsigned integer with two long (32bit) unsigned integers. For 32 bit unsinged integers we use currency variables (because they can hold all the possible values), and this is the return type from binary.xxx() functions. For 64 bit unsigned integers we use decimal type. So a 0xFFFF_FFFF_FFFF_FFFF is a decimal type with the value of an unsigned integer 64bit equal to 18446744073709551615 decimal. We can use 18446744073709551615@ to define decimal literal. The 0xFFFF_FFFF_FFFF_FFFF&& literal is a signed long long and has value -1. M2000 use & for signed long, so 0xFFFF_FFFF& is -1 long, and use % for signed integer 16bit, so 0xFFFF% is -1. Also there is the Byte which is always unsigned from 0 to 255. So we make a HiLow variable (a buffer type) z and that became a closure to final lambda function (buffers are reference type so we put the pointer to lambda). Using buffer we can pass the address using z(0) which 0 is the offset of first item (the z has one item now but we can make it with many more) to an external function (passing the address is same like passing by reference but not the reference of the reference, so the reference stay as is, the value can be change). M2000 functions can use "reference of reference" if we use &z from each side (from caller and callee should defined as byreference using &), so if we pass a reference type by reference you can change the reference not only the value. This isn't something to do here. We only use the union to get the value of low long or high long  of the 64 bit long long.


Module Shift64bit {
  bit.shift=lambda ->{
    structure HiLow {
      {ab as long long} 'union with 2 long
      a as long, b as long
    }
    HiLow z ' make a z and put as closure to lambda
    =lambda z (z|ab, b, only32bit as boolean=false)-> {
      if abs(b)>63 then
        z|ab=0
      else.if b<-31 then
        b+=32
        z|a=binary.shift(z|b, b)
        z|b=0
      else.if b<0 then
        mask=binary.shift(0xFFFFFFFF, 32+b)
        z|a=binary.and(binary.rotate(z|b, b), mask)+binary.shift(z|a, b)
        z|b=binary.shift(z|b, b)
      else.if b=0 then
      else.if b<31 then
        mask=binary.shift(0xFFFFFFFF, b-32)
        z|b=binary.shift(z|b, b)+binary.and(binary.rotate(z|a, b), mask)
        z|a=binary.shift(z|a, b)
      else
        b-=32
        z|b=binary.shift(z|a, b)
        z|a=0
      end if
      if only32bit then =z|a else =z|ab  
    }
  }()
  a=0x1234AAAA
  aa=a+0xFFFF_AAAA_0000_0000
  for n=-64 to 64 step 4
    if abs(n)>63 then
      b=0#
      c=0@
    else
      refresh 100
      if abs(n)>31 then
        b=0
      else
        b=binary.shift(a, n)
      end if
      c=bit.shift(aa, n)
    end if
    print "bit shift:";n
    
    hex a
    hex b
    hex aa
    hex c
    push key$: drop
  next
  refresh 25
}
Shift64bit

 

Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.