Recent

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

LemonParty

  • Hero Member
  • *****
  • Posts: 560
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: 2071
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

  • Hero Member
  • *****
  • Posts: 560
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

  • Hero Member
  • *****
  • Posts: 560
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: 2593
    • 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: 19438
  • Glad to be alive.
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
Any "programmer" that knows only one programming language is not a programmer

 

TinyPortal © 2005-2018