Complement a Number

Started by Baggey, October 07, 2023, 18:10:04

Previous topic - Next topic

Baggey

As far as im aware there is no function to complement the Bits of a Number ::)

Ive been Implementing Some Routines that i need to Complement certain bits or a number of bits.

It could be added to by Left to right and even a certain Bit. But I have no need for this right now!

So I put this together Complementing from Right to Left.

Runnable BlitzMaxNG code

' Takes a Number And Complements each Bit
' The Not Command only does the first Bit
' Sometimes you need to complement all bits or a certain number
' So I wrote this may come in handy for someone
' Written by Baggey

SuperStrict

Global DD00:Int=255

'DD00:&3 ' And DD00 with 3 ie, 00000011 Retrieve first 2 Bits

DD00=255

Print RSet(Bin(DD00),8)

Print RSet(Bin(Com(DD00,4)),8)

Function Com:Int(Num:Int, NumOfBits:Int)

     ' Starts NumOFBits from Right to Left

     If NumOfBits = Null Return Num

     Local Bit:Int=1

     Repeat

        If (Num & Bit) = 0 Then Num = (Num | Bit) Else Num = (Num &~ Bit)
       
        Bit = Bit Shl 1

        NumOfBits:-1
       
     Until (NumOfBits=0)

     Return Num

End Function

As always if you find this useful use it as you will if not Simply ignore it.

Kind Regards Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Midimaster

I guess this can be done with less code:

Function Com:Int(Num:Int, NumOfBits:Int)
    Local Bit:Int = 2^NumOfBits-1
    Return num ~ bit
End Function
...back from Egypt

Baggey

I didnt think of that ::)

I know you can do 2^0, 2^1 etc.. for individual bits. Too get your relevant bit, but doing the lot in one go and then Xoring for the return Neat!

Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Derron

#3
SuperStrict
Framework Brl.StandardIO


Function Com:Int(Num:Int, NumOfBits:Int)
    Local Bit:Int = 2^NumOfBits-1
    Return num ~ bit
End Function

'in NG we can "inline" it to avoid function call costs if compiler does not do for us
'(I assume GCC already inlines both variants here already)
Function Com2:Int(Num:Int, NumOfBits:Int) Inline
    Return num ~ (1 shl NumOfBits - 1)
End Function

print 1 shl 0
print 1 shl 1
print 1 shl 2
print 1 shl 3


print Com(10, 5) + ", " + Com(5002015, 1)
print Com2(10, 5) + ", " + Com2(5002015, 1)


local runs:int = 100000000
local result:int, t:Int

result = 0
t = Millisecs()
For local i:int = 0 until runs
result :+ Com(i, 3)
Next
print "result " + result + " in " + (Millisecs()-t)+"ms."

result = 0
t = Millisecs()
For local i:int = 0 until runs
result :+ Com2(i, 3)
Next
print "result " + result + " in " + (Millisecs()-t)+"ms."

release:
result 887459712 in 238ms.
result 887459712 in 14ms.

debug:
result 887459712 in 8187ms.
result 887459712 in 7115ms.

PS:
result = 0
t = Millisecs()
For local i:int = 0 until runs
result = result + i ~ (1 shl 3 - 1)
Next

is again 200% faster ... why? because NG already replaces the "1 shl 3 - 1" with "7" during generation of the C code (static expression) and thus of course replacing most of the calculation already. So if you try to compare this, then be aware of "why" it is so much faster.

bye
Ron

Baggey

Wow, @Derron

Thankyou for that. You've given me an idea for speed testing my functions Thankyou 8)

com() seems to be the smallest and neatest code however running your speed test gives me a good idea, of which way to go with the coding.

I Put your code together and consolidated my code and ran them to see the Speed Benefits!

I think im going to start working through my Functions to see if i can change and re-write for Speed.

As you probably understand writting an Emulator must have the fastest code execution because of the shear overhead of the instructions.

all methods get/give the same result but speed for me is always of upmost importance ;)

Here is a Runnable Speed test example of all way's in BlitzmaxNG

' Complement Speed Tester

SuperStrict
Framework Brl.StandardIO


Function Com:Int(Num:Int, NumOfBits:Int)
    Local Bit:Int = 2^NumOfBits-1
    Return num ~ bit
End Function

'in NG we can "inline" it to avoid function call costs if compiler does not do for us
'(I assume GCC already inlines both variants here already)
Function Com2:Int(Num:Int, NumOfBits:Int) Inline
    Return num ~ (1 Shl NumOfBits - 1)
End Function

Function Com3:Int(Num:Int, NumOfBits:Int)

     ' Starts NumOFBits from Right to Left

     If NumOfBits = Null Return Num

     Local Bit:Int=1

     Repeat

        If (Num & Bit) = 0 Then Num = (Num | Bit) Else Num = (Num &~ Bit)
      
        Bit = Bit Shl 1

        NumOfBits:-1
      
     Until (NumOfBits=0)

     Return Num

End Function


Local runs:Int = 100000000
Local result:Int, t:Int

Print

result = 0
t = MilliSecs()
For Local i:Int = 0 Until runs
result :+ Com(i, 3)
Next
Print "result " + result + " in " + (MilliSecs()-t)+"ms.   Midimasters"

result = 0
t = MilliSecs()
For Local i:Int = 0 Until runs
result :+ Com2(i, 3)
Next
Print "result " + result + " in " + (MilliSecs()-t)+"ms.   Derrons WOW 56ms!"

result = 0
t = MilliSecs()
For Local i:Int = 0 Until runs
result :+ Com3(i, 3)
Next
Print "result " + result + " in " + (MilliSecs()-t)+"ms.   Baggeys"

result = 0
t = MilliSecs()
For Local i:Int = 0 Until runs
result = result + i ~ (1 Shl 3 - 1)
Next

Print
Print "result " + result + " in " + (MilliSecs()-t)+"ms.   No Function Call!"
 
Conclusion. I suppose that unless we understand how the Blitzmax compiler works. We would not necessarily know which things to do, to get the best speeds/results anyways ???

Kind Regards Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Midimaster

I run your example and got this results:
result 887459712 in 10ms.   Midimasters
result 887459712 in 10ms.   Derrons
result 887459712 in 57ms.   Baggeys

result 887459712 in 60ms.   No Function Call
...back from Egypt

col

#6
QuoteWe would not necessarily know which things to do, to get the best speeds/results anyways
This applies to all programming languages, and your its your algorithms and logic that matter the most.

A good rule of thumb would be to always try to use the correct datatypes for your goal. using strings to do bit manipulation is a no-no in anywlanguage.

The optimisation that Derron speaks of, the '(1 shl 3 - 1)' would be optimised by the backend c compiler even if the 'max converter to c didn't do it, so yeah I wouldn't worry so much unless you have issues.
https://github.com/davecamp

"When you observe the world through social media, you lose your faith in it."

Baggey

Quote from: Midimaster on October 08, 2023, 12:56:58I run your example and got this results:
result 887459712 in 10ms.   Midimasters
result 887459712 in 10ms.   Derrons
result 887459712 in 57ms.   Baggeys

result 887459712 in 60ms.   No Function Call

On my PC i get

result 887459712 in 926ms.   Midimasters
result 887459712 in 57ms.   Derrons WOW 56ms!
result 887459712 in 236ms.   Baggeys

result 887459712 in 55ms.   No Function Call!

Process complete

Im Running Windows 10?

So Maybe the type of setup we have ie, 32 bit or 64 bit, Linux, Mac etc may have something todo with the different results oh im on 50Hz, 240v here?
Maybe what runs quicker on my system may not on someone else's hmm ::)

As always, I appreciate anyone's help and will not take any offence to criticisms or idea's. Im here to learn and perfect my coding. :)

As we say there are more way's than one to skin a cat!? It don't sound right really but that's what we say here.

Kindest Regards to anyone who try to help me! :D Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Baggey

Quote from: col on October 08, 2023, 13:42:26
QuoteWe would not necessarily know which things to do, to get the best speeds/results anyways
This applies to all programming languages, and your its your algorithms and logic that matter the most.

A good rule of thumb would be to always try to use the correct datatypes for your goal. using strings to do bit manipulation is a no-no in anywlanguage.

The optimisation that Derron speaks of, the '(1 shl 3 - 1)' would be optimised by the backend c compiler even if the 'max converter to c didn't do it, so yeah I wouldn't worry so much unless you have issues.

Yeah, I kinda get that, as when using a short i get an automatic wrap around at 65535. But if you use an int you have to and 65535 to catch it :-X

Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 24GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!