Swapping bits

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
newby12
Posts: 33
Joined: Dec 26, 2021 1:57

Swapping bits

Post by newby12 »

Since you can't swap mids.

str1 = "001110" : swap mid( str1 , 5 , 2 ) , mid( str1 , 1 , 2 ) , can't do it.

So i came up with a work-around. using ushort ptr's

Code: Select all

do
    
    dim as string n1 = right( "00" + bin( int( rnd *4 ) ) , 2 )
    
    dim as ushort ptr usp = cptr( ushort ptr , strptr( n1 ) )
        
    dim as ulongint v1 = *usp
    
    if v1 = 12336 then v1 = 0
    if v1 = 12337 then v1 = 2
    if v1 = 12592 then v1 = 1
    if v1 = 12593 then v1 = 3
    
    print n1 , *usp ,  v1
    
    sleep
    
loop until inkey = chr( 27 )

end
Last edited by fxm on Jan 26, 2022 9:49, edited 1 time in total.
Reason: Topic moved to the dedicated forum.
badidea
Posts: 2521
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Swapping bits

Post by badidea »

Hum, where have I seen that coding style before?
dodicat
Posts: 7391
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Swapping bits

Post by dodicat »

Hello newby12
You can swap mids in a macro.

Code: Select all

#macro switch(a,b)
scope
    var temp=a
    a=b
    b=temp
end scope
#endmacro

var str1 = "001110" 
print str1
 switch( mid( str1 , 5 , 2 ) , mid( str1 , 1 , 2 ))
print str1
sleep

 
newby12
Posts: 33
Joined: Dec 26, 2021 1:57

Re: Swapping bits

Post by newby12 »

if v1 = 12336 then v1 = 0
if v1 = 12337 then v1 = 2

if v1 = 12592 then v1 = 1
if v1 = 12593 then v1 = 3

The problem is , 2 and 1 are flopped. 1 ( 12592 ) is greater than 2 ( 12337 )
So you have to take that into account when you compare the the 2 sets of 2 bits..
fxm
Moderator
Posts: 11041
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Swapping bits

Post by fxm »

If your problem was clearly stated with input data and the expected results, we could more easily answer you, and this since your first post 6 days ago on this subject (viewtopic.php?p=289171#p289171).
Even now, it's still not clear what you want to achieve.
newby12
Posts: 33
Joined: Dec 26, 2021 1:57

Re: Swapping bits

Post by newby12 »

@fxm

you can swap vars , swap var1 , var2
you can swap strings , swap s1 , s2
you can swap string indexes , swap s[0] , s[3]

but if you want to swap the middle of strings you can't do it with "SWAP". You have to figure another way , and it gets messy and cumbersome.

but dodicat solved the problem , with his dandy macro above..
newby12
Posts: 33
Joined: Dec 26, 2021 1:57

Re: Swapping bits

Post by newby12 »

I remember when i first started programming.

It was Dos 5 and GW Basic..
i used to write my asm code in Dos debug , and and poke it to an unused page on the video buffer. then goto the buffer location..
It was a fast and simple way to implement mouse poutines. and other small and fast asm...

Then came QBasic.. Then QBasic 64 and now there's FreeBasic.. Which tops them all..
I spent over a year searching through every type of basic on the internet and finally found FreeBasic...
Now I've cleaned up my hard drive and only have FreeBasic on my computer..
Munair
Posts: 1274
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: Swapping bits

Post by Munair »

newby12 wrote: Jan 28, 2022 2:33 but if you want to swap the middle of strings you can't do it with "SWAP". You have to figure another way , and it gets messy and cumbersome.

but dodicat solved the problem , with his dandy macro above..
The macro is possible thanks to the mid-statement. Same but without macro:

Code: Select all

dim str1 as string = "001110"
dim temp as string

temp = mid(str1, 5, 2)
mid(str1, 5, 2) = mid(str1, 1, 2)
mid(str1, 1, 2) = temp

print str1
It is not messy or cumbersome at all. You can also turn it into a subroutine to avoid "passing" mid() around:

Code: Select all

declare sub SwapInstr(s as string, a as ubyte, b as ubyte, c as ubyte, d as ubyte)

dim str1 as string = "001110"

print str1
SwapInstr(str1, 5, 2, 1, 2)
print str1
end

sub SwapInstr(s as string, a as ubyte, b as ubyte, c as ubyte, d as ubyte)
  dim tmp as string = mid(s, a, b)
  mid(s, a, b) = mid(s, c, d)
  mid(s, c, d) = tmp
end sub
Munair
Posts: 1274
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: Swapping bits

Post by Munair »

In this example, bytes are swapped directly, which avoids using the slow mid() statement/function. Now the positions are zero-based.

Code: Select all

declare sub SwapInstr(s as string, a as ubyte, b as ubyte)

dim s as string = "001110"

print s

SwapInstr(s, 0, 4)
SwapInstr(s, 1, 5)
print s
end

sub SwapInstr(s as string, a as ubyte, b as ubyte)
  dim l as uinteger = len(s)
  if a < l then
    if b < l then
      swap s[a], s[b]
    end if
  end if
end sub
In my test, swapping bytes directly using two procedure calls, is almost 10 times faster than mid() using a single procedure call. ;-)
Munair
Posts: 1274
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: Swapping bits

Post by Munair »

For completeness, here is a speed test to see which method is fastest. It includes dodicat's macro. No compiler optimization switches were used.

Code: Select all

' swapping string bytes speed test by Munair
' ----------------------------------------------------------------
declare sub SwapInstr1(s as string, a as ubyte, b as ubyte)
declare sub SwapInstr2(s as string, a as ubyte, b as ubyte)
declare sub SwapInstr3(s as string, a as ubyte, b as ubyte, c as ubyte, d as ubyte)

#macro switch(a,b)
  ' about as fast as SwapInstr3
  scope
      var temp=a
      a=b
      b=temp
  end scope
#endmacro

dim s as string = "001111"
dim i as uinteger
dim t as double

print "with bytes:"
t = timer
for i = 0 to 100000000
  SwapInstr1(s, 0, 4)
  SwapInstr1(s, 1, 5)
next
print timer - t

print "with bytes using swap():"
t = timer
for i = 0 to 100000000
  SwapInstr2(s, 0, 4)
  SwapInstr2(s, 1, 5)
next
print timer - t

print "with mid:"
t = timer
for i = 0 to 100000000
  SwapInstr3(s, 5, 2, 1, 2)
next
print timer - t

print "with macro(mid, mid):"
t = timer
for i = 0 to 100000000
  switch(mid(s, 5, 2), mid(s, 1, 2))
next
print timer - t

end

sub SwapInstr1(s as string, a as ubyte, b as ubyte)
  ' almost as fast as SwapInstr2
  dim temp as ubyte = s[a]
  dim l as uinteger = len(s)
  if a < l then
    if b < l then
      s[a] = s[b]
      s[b] = temp
    end if
  end if
end sub

sub SwapInstr2(s as string, a as ubyte, b as ubyte)
  ' slightly faster than SwapInstr1
  dim l as uinteger = len(s)
  if a < l then
    if b < l then
      swap s[a], s[b]
    end if
  end if
end sub

sub SwapInstr3(s as string, a as ubyte, b as ubyte, c as ubyte, d as ubyte)
  ' almost 10 times slower than SwapInstr1 and SwapInstr2
  dim tmp as string = mid(s, a, b)
  mid(s, a, b) = mid(s, c, d)
  mid(s, c, d) = tmp
end sub
Output:

Code: Select all

1. with bytes:
   1.470577001571655
2. with bytes using swap():
   1.368752956390381
3. with mid:
   9.857635974884033
4. with macro(mid, mid):
   9.665795087814331
Tested on Manjaro x64 with fbc 1.08:
Last edited by Munair on Jan 29, 2022 7:04, edited 1 time in total.
newby12
Posts: 33
Joined: Dec 26, 2021 1:57

Re: Swapping bits

Post by newby12 »

Thanks for the assistance..
Post Reply