Recent

Author Topic: How to set the top nonzero bit of integer to zero?  (Read 583 times)

LemonParty

  • Sr. Member
  • ****
  • Posts: 353
How to set the top nonzero bit of integer to zero?
« on: October 18, 2025, 08:44:12 pm »
For example:
Reset(7) = 3
Reset(3) = 1
Reset(1) = 0

I know in x86 that can be done with Bsr and Btr instruction. Is there a non loop decision that is crosspatform?
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

Warfley

  • Hero Member
  • *****
  • Posts: 2020
Re: How to set the top nonzero bit of integer to zero?
« Reply #1 on: October 18, 2025, 08:51:36 pm »
Something like:
Code: Pascal  [Select][+][-]
  1. function ResetMSBit(const x: QWord): QWord; inline;
  2. begin
  3.   Result := x And not (1 shl BsrQWord(x));
  4. end;

BsrXYZ is provided by the system unit and will provide functionality on each platform. Where supported it directly uses the assembly instruction, but on platforms it doesn't have it, it's a regular implementation

Alternatively:
Code: Pascal  [Select][+][-]
  1. function ResetMSBit(const x: QWord): QWord; inline;
  2. var
  3.   i: Integer;
  4. begin
  5.   for i:=63 downto 0 do
  6.     if ((1 shl i) And x) <> 0 then
  7.       Exit(Result and not (1 shl i));
  8.   Result := 0;
  9. end;
« Last Edit: October 18, 2025, 08:55:09 pm by Warfley »

LemonParty

  • Sr. Member
  • ****
  • Posts: 353
Re: How to set the top nonzero bit of integer to zero?
« Reply #2 on: October 18, 2025, 09:10:54 pm »
I guess I found the solution:
Code: Pascal  [Select][+][-]
  1. function ResetMSBit(u: UInt32): UInt32;inline;
  2. begin
  3.   if u <> 0
  4.     then Result:= u and RolDWord(-2, BsrDWord(u))
  5.     else Result:= 0;
  6. end;
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

LemonParty

  • Sr. Member
  • ****
  • Posts: 353
Re: How to set the top nonzero bit of integer to zero?
« Reply #3 on: October 18, 2025, 09:22:42 pm »
This is also work:
Code: Pascal  [Select][+][-]
  1. function ResetMSBit(u: UInt32): UInt32;inline;
  2. begin
  3.   Result:= u and RolDWord(-2, BsrDWord(u));
  4. end;
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

avra

  • Hero Member
  • *****
  • Posts: 2566
    • Additional info
Re: How to set the top nonzero bit of integer to zero?
« Reply #4 on: October 22, 2025, 07:23:42 pm »
If you use trunk fpc, then just include sysutils and syshelpers and you can do something like:

Code: Pascal  [Select][+][-]
  1. ...
  2. var
  3.   MyDword: dword;
  4. begin
  5.   MyDword            := %111000111000111000111;
  6.   MyDword.Words[0]   := 77;
  7.   MyDword.Bits[9]    := true;
  8.   MyDword.Nibbles[0] := $A;
  9.   WriteLn('MyDword.ToBinString      = ', MyDword.ToBinString);
  10.   WriteLn('MyDword.HighestSetBitPos = ' + MyDword.HighestSetBitPos.ToString);
  11.   WriteLn('MyDword.SetBitsCount     = ' + MyDword.SetBitsCount.ToString);
  12.   WriteLn('MyDword.ToHexString      = ', MyDword.ToHexString);
  13. ...
  14.  
Full example can be found in \fpcsrc\packages\rtl-objpas\examples\syshelpersdemo.pas.
 
If you are not using trunk, then just install bithelpers package from my signature (you can find it in OPM as well), and you will be able to do the same.
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

Thaddy

  • Hero Member
  • *****
  • Posts: 18304
  • Here stood a man who saw the Elbe and jumped it.
Re: How to set the top nonzero bit of integer to zero?
« Reply #5 on: October 22, 2025, 07:37:10 pm »
@Avra
Yes, that's why we wrote it ... :D
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

 

TinyPortal © 2005-2018