Lazarus

Free Pascal => General => Topic started by: Thaddy on October 10, 2019, 10:42:44 am

Title: Some fun with bitmanipulations
Post by: Thaddy on October 10, 2019, 10:42:44 am
I have submitted a patch to add bitwise manipulations on any ordinals in trunk (not accepted yet) but since it can also be used in other versions I separated it into a unit. (attached)
I wrote it to manipulate hardware on a Raspberry Pi, but it is also useful for other purposes.
The code is simple, concise, precise and type safe.
Example:
Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$H+}
  2. uses
  3.   ordinalbits;
  4.  
  5. var a:ShortInt = 0;
  6. begin
  7.   writeln(a.ToBinString);
  8.   a.setbit(7);
  9.   writeln(a.ToBinString);
  10.   writeln(a);                    // should be -128
  11.   a.Togglebit(1);                // should be -126      
  12.   writeln(a.ToBinString);
  13.   writeln(a.testbit(1));         // should be true
  14.   writeln(a);
  15.   a.Togglebit(1);          
  16.   writeln(a.ToBinString);
  17.   writeln(a.testbit(1));         // should be false  
  18.   a.togglebit(7);                // should be zero
  19.   writeln(a.ToBinString);
  20.   writeln(a.testbit(7));         // should be false
  21.   writeln(a);
  22.   writeln(High(TQwordBitIndex)); // should be 63
  23. end.
This specific version works from version 3.0.0.
I think this was really missing. I hope you fillet me if there's something to improve..
It supports all ordinal types for which there is already a type helper, except Booleans, which are strictly speaking also ordinals.
I hope you like the simple code ... :D
Title: Re: Some fun with bitmanipulations
Post by: howardpc on October 10, 2019, 11:03:06 am
Thanks Thaddy.
I found I needed to add a {$RangeChecks off}  to ordinalbits.inc to get your test program to succeed.
Title: Re: Some fun with bitmanipulations
Post by: MarkMLl on October 10, 2019, 12:10:16 pm
Is this tested on both little- and big-endian systems?

Memories writing Modula-2 code where different compilers ordered the content of a bitset differently.

MarkMLl
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 10, 2019, 12:14:24 pm
I found I needed to add a {$RangeChecks off}  to ordinalbits.inc to get your test program to succeed.
That should not be the case. (I am sure about the patch nbr 4) Maybe I made a typo during general porting, I will look into it.
[edit]
Can not reproduce it. Can you give me the line where it fails? Everything is checked with {$rangechecks on}, hence I defined the ranges specifically. That's how I caught a rangecheck during testing the patch. Any help would be appreciated.
Note that if there is an impossible - for the ordinal - index value then it should indeed fail with a rangecheck error. That is intentional.
E.g. on a byte the range is 0..7 and 8 will throw a rangecheck error. Similar for the others.
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 10, 2019, 12:16:25 pm
Is this tested on both little- and big-endian systems?

Memories writing Modula-2 code where different compilers ordered the content of a bitset differently.

MarkMLl

The code extends the already available helpers. It assumes no specific bitness.
Title: Re: Some fun with bitmanipulations
Post by: MarkMLl on October 10, 2019, 12:40:32 pm
Have the helpers been checked recently? :-)

I used to make a point of running up a SPARC-based system every so often to check this sort of thing, but at present it's not as easy for me as it was a year ago.
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 10, 2019, 12:56:08 pm
I used to have a big endian machine (a powerpc) in fact I still have it, but it is a museum piece occupying attic space on display at my personal museum and is just lying beautiful in its case.... It is pretty dead...
But if the helpers were not sound that would have shown up in bug reports. The code I wrote is fully portable.
Title: Re: Some fun with bitmanipulations
Post by: howardpc on October 10, 2019, 12:58:48 pm
I found I needed to add a {$RangeChecks off}  to ordinalbits.inc to get your test program to succeed.
Can not reproduce it. Can you give me the line where it fails?
The first call fails (  a.setbit(7); )
This is on 64-bit Linux
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 10, 2019, 01:17:38 pm
The first call fails (  a.setbit(7); )
This is on 64-bit Linux
That should not happen, because of:
Code: Pascal  [Select][+][-]
  1.   // make type safe ranges
  2.   // 0..7
  3.   TByteBitIndex = 0..Pred(SizeOf(Byte) * 8);
  4.   TShortIntBitIndex = TByteBitIndex;
Title: Re: Some fun with bitmanipulations
Post by: howardpc on October 10, 2019, 01:20:26 pm
Whether or not it "should" I am simply reporting that it does.
Title: Re: Some fun with bitmanipulations
Post by: MarkMLl on October 10, 2019, 01:32:56 pm
I used to have a big endian machine (a powerpc) in fact I still have it, but it is a museum piece occupying attic space on display at my personal museum and is just lying beautiful in its case.... It is pretty dead...
But if the helpers were not sound that would have shown up in bug reports. The code I wrote is fully portable.

I've got a 1U SPARC here onto which I've finally managed to get the current Debian, but I can't remember (and have very limited time to check) what the situation is regarding FPC since the OS is now 64-bit and I haven't a clue how good its multiarch support is.

For a substantial number of years I had an adequate number of running SPARC/PPC/ARM systems running Lazarus/FPC natively, and I can assure you that problems /do/ show up due to unexpected endianness dependency and- more urgently- operations which the OS thinks should be word-aligned.

I'll try to fire the SPARC up and see where I get to, but I've got rather a lot of problems at the moment.
Title: Re: Some fun with bitmanipulations
Post by: Bart on October 10, 2019, 01:43:33 pm
a.setbit(7) evaluates to ShortInt := ShortInt or 128.
This give a range check error, not only on 64-bit platforms b.t.w.

Try to compile this:

Code: Pascal  [Select][+][-]
  1. var
  2.   a: shortint = 0 or 128;

This gives: Error: range check error while evaluating constants (128 must be between -128 and 127)

You also cannot do Integer.SetBit(31), but that gives a compile time error:  range check error while evaluating constants (2147483648 must be between -2147483648 and 2147483647)

Bart
Title: Re: Some fun with bitmanipulations
Post by: Bart on October 10, 2019, 02:32:07 pm
Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$H+}
  2. {$R+}
  3. uses
  4.   sysutils, ordinalbits;
  5.  
  6. var a:ShortInt = 0;
  7.  
  8.     HighB: TByteBitIndex = High(TByteBitIndex);             B: Byte = 0;
  9.     HighSh: TShortIntBitIndex = High(TShortIntBitIndex);    Sh: ShortInt = 0;
  10.     HighW: TWordBitIndex = High(TWordBitIndex);             W: Word = 0;
  11.     HighSm: TSmallIntBitIndex = High(TSmallIntBitIndex);    Sm: SmallInt = 0;
  12.     HighC: TCardinalBitIndex = High(TCardinalBitIndex);     C: Cardinal = 0;
  13.     HighLI: TIntegerBitIndex = High(TIntegerBitIndex);      LI: Integer = 0;
  14.     HighNU: TNativeUIntBitIndex = High(TNativeUIntBitIndex);NU: NativeUInt = 0;
  15.     HighNI: TNativeIntBitIndex = High(TNativeIntBitIndex);  NI: NativeInt = 0;
  16.     HighQ: TQwordBitIndex = High(TQwordBitIndex);           Q: QWORD = 0;
  17.     HighI64: TInt64BitIndex = High(TInt64BitIndex);         I64: Int64 = 0;
  18.  
  19.  
  20. begin
  21.   {$ifdef cpu32}
  22.   writeln('Compiled for 32-bit');
  23.   {$endif}
  24.   {$ifdef cpu64}
  25.   writeln('Compiled for 64-bit');
  26.   {$endif}
  27.  
  28.   try
  29.     write(format('Byte.SetBit(%.2d)      : ',[HighB]));
  30.     B.SetBit(HighB);
  31.     writeln(format('OK: [%s] ',[B.ToBinString]));
  32.   except
  33.     on e: exception do writeln(e.message);
  34.   end;
  35.  
  36.   try
  37.     write(format('ShortInt.SetBit(%.2d)  : ',[HighSh]));
  38.     Sh.SetBit(HighSh);
  39.     writeln(format('OK: [%s] ',[Sh.ToBinString]));
  40.   except
  41.     on e: exception do writeln(e.message);
  42.   end;
  43.  
  44.   try
  45.     write(format('Word.SetBit(%d)      : ',[HighW]));
  46.     W.SetBit(HighW);
  47.     writeln(format('OK: [%s] ',[W.ToBinString]));
  48.   except
  49.     on e: exception do writeln(e.message);
  50.   end;
  51.  
  52.   try
  53.     write(format('SmallInt.SetBit(%d)  : ',[HighSm]));
  54.     Sm.SetBit(HighSm);
  55.     writeln(format('OK: [%s] ',[Sm.ToBinString]));
  56.   except
  57.     on e: exception do writeln(e.message);
  58.   end;
  59.  
  60.   try
  61.     write(format('Cardinal.SetBit(%d)  : ',[HighC]));
  62.     C.SetBit(HighC);
  63.     writeln(format('OK: [%s] ',[C.ToBinString]));
  64.   except
  65.     on e: exception do writeln(e.message);
  66.   end;
  67.  
  68.   try
  69.     write(format('LongInt.SetBit(%d)   : ',[HighLI]));
  70.     LI.SetBit(HighLI);                              //LI.SetBit(31) gives compiletime rangecheck error
  71.     writeln(format('OK: [%s] ',[LI.ToBinString]));
  72.   except
  73.     on e: exception do writeln(e.message);
  74.   end;
  75.  
  76.   try
  77.     write(format('NativeUint.SetBit(%d): ',[HighNU]));
  78.     NU.SetBit(HighNU);
  79.     writeln(format('OK: [%s] ',[NU.ToBinString]));
  80.   except
  81.     on e: exception do writeln(e.message);
  82.   end;
  83.  
  84.   try
  85.     write(format('NativeInt.SetBit(%d) : ',[HighNI]));
  86.     NI.SetBit(HighNI);                              //NI.SetBit(31) gives compiletime rangecheck error in 32-bit mode, NI.SetBit(63) is allowed in 64-bit
  87.     writeln(format('OK: [%s] ',[NI.ToBinString]));
  88.   except
  89.     on e: exception do writeln(e.message);
  90.   end;
  91.  
  92.   try
  93.     write(format('QWORD.SetBit(%d)     : ',[HighQ]));
  94.     Q.SetBit(HighQ);
  95.     writeln(format('OK: [%s] ',[Q.ToBinString]));
  96.   except
  97.     on e: exception do writeln(e.message);
  98.   end;
  99.  
  100.   try
  101.     write(format('Int64.SetBit(%d)     : ',[HighI64]));
  102.     I64.SetBit(HighI64);
  103.     writeln(format('OK: [%s] ',[I64.ToBinString]));
  104.   except
  105.     on e: exception do writeln(e.message);
  106.   end;
  107. end.

Output (on Windows):
Code: [Select]
Compiled for 32-bit
Byte.SetBit(07)      : OK: [10000000]
ShortInt.SetBit(07)  : Range check error
Word.SetBit(15)      : OK: [1000000000000000]
SmallInt.SetBit(15)  : Range check error
Cardinal.SetBit(31)  : OK: [10000000000000000000000000000000]
LongInt.SetBit(31)   : OK: [10000000000000000000000000000000]
NativeUint.SetBit(31): OK: [10000000000000000000000000000000]
NativeInt.SetBit(31) : OK: [10000000000000000000000000000000]
QWORD.SetBit(63)     : OK: [1000000000000000000000000000000000000000000000000000000000000000]
Int64.SetBit(63)     : OK: [1000000000000000000000000000000000000000000000000000000000000000]

C:\Users\Bart\LazarusProjecten\bugs\Console\ordinalbits>bits
Compiled for 64-bit
Byte.SetBit(07)      : OK: [10000000]
ShortInt.SetBit(07)  : Range check error
Word.SetBit(15)      : OK: [1000000000000000]
SmallInt.SetBit(15)  : Range check error
Cardinal.SetBit(31)  : OK: [10000000000000000000000000000000]
LongInt.SetBit(31)   : OK: [10000000000000000000000000000000]
NativeUint.SetBit(63): OK: [1000000000000000000000000000000000000000000000000000000000000000]
NativeInt.SetBit(63) : OK: [1000000000000000000000000000000000000000000000000000000000000000]
QWORD.SetBit(63)     : OK: [1000000000000000000000000000000000000000000000000000000000000000]
Int64.SetBit(63)     : OK: [1000000000000000000000000000000000000000000000000000000000000000]

Notice that at runtime you can do Integer.SetBit(31), but at compiletime this is not allowed.
The same for NativeInt in 32-bit mode.

(I would have expected that this problem would arise for all of the unsigned ordinals.)

Wondering what will happen on 16-bit DOS.

Bart
Title: Re: Some fun with bitmanipulations
Post by: Bart on October 10, 2019, 03:23:26 pm
Casting everything to an unsigned type might be a solution?

In ordinalbits.pas:
Code: Pascal  [Select][+][-]
  1. implementation
  2. {$MACRO ON}
  3. // byte
  4. {$define TORDINALBITHELPER:=TByteBitHelper}
  5. {$define TORDINALBITINDEX:=TByteBitIndex}
  6. {$define TORDINALTYPE:=byte}
  7. {$define TORDINALUNSIGNEDTYPE:=byte}
  8. {$i ordinalbits.inc}
  9. // shortint
  10. {$define TORDINALBITHELPER:=TShortIntBitHelper}
  11. {$define TORDINALBITINDEX:=TShortIntBitIndex}
  12. {$define TORDINALTYPE:=ShortInt}
  13. {$define TORDINALUNSIGNEDTYPE:=byte}
  14. {$i ordinalbits.inc}
  15. // word
  16. {$define TORDINALBITHELPER:=TWordBitHelper}
  17. {$define TORDINALBITINDEX:=TWordBitIndex}
  18. {$define TORDINALTYPE:=Word}
  19. {$define TORDINALUNSIGNEDTYPE:=Word}
  20. {$i ordinalbits.inc}
  21. // smallint
  22. {$define TORDINALBITHELPER:=TSmallIntBitHelper}
  23. {$define TORDINALBITINDEX:=TSmallIntBitIndex}
  24. {$define TORDINALTYPE:=SmallInt}
  25. {$define TORDINALUNSIGNEDTYPE:=Word}
  26. {$i ordinalbits.inc}
  27. // cardinal
  28. {$define TORDINALBITHELPER:=TCardinalBitHelper}
  29. {$define TORDINALBITINDEX:=TCardinalBitIndex}
  30. {$define TORDINALTYPE:=Cardinal}
  31. {$define TORDINALUNSIGNEDTYPE:=Cardinal}
  32. {$i ordinalbits.inc}
  33. // integer
  34. {$define TORDINALBITHELPER:=TIntegerBitHelper}
  35. {$define TORDINALBITINDEX:=TIntegerBitIndex}
  36. {$define TORDINALTYPE:=integer}
  37. {$define TORDINALUNSIGNEDTYPE:=DWORD}
  38. {$i ordinalbits.inc}
  39. // nativeuInt
  40. {$define TORDINALBITHELPER:=TNativeUintBitHelper}
  41. {$define TORDINALBITINDEX:=TNativeUintBitIndex}
  42. {$define TORDINALTYPE:=NativeUint}
  43. {$define TORDINALUNSIGNEDTYPE:=NativeUint}
  44. {$i ordinalbits.inc}
  45. // nativeint
  46. {$define TORDINALBITHELPER:=TNativeIntBitHelper}
  47. {$define TORDINALBITINDEX:=TNativeIntBitIndex}
  48. {$define TORDINALTYPE:=NativeInt}
  49. {$define TORDINALUNSIGNEDTYPE:=NativeUInt}
  50. {$i ordinalbits.inc}
  51. // qword
  52. {$define TORDINALBITHELPER:=TQwordBitHelper}
  53. {$define TORDINALBITINDEX:=TQwordBitIndex}
  54. {$define TORDINALTYPE:=Qword}
  55. {$define TORDINALUNSIGNEDTYPE:=QWORD}
  56. {$i ordinalbits.inc}
  57. // int64
  58. {$define TORDINALBITHELPER:=TInt64BitHelper}
  59. {$define TORDINALBITINDEX:=TInt64BitIndex}
  60. {$define TORDINALTYPE:=Int64}
  61. {$define TORDINALUNSIGNEDTYPE:=QWORD}
  62. {$i ordinalbits.inc}
  63. end.  

And then ordinalbits.inc:
Code: Pascal  [Select][+][-]
  1. // note that all the typecasts are necessary when doing bit manipulations
  2. // also note a boolean cast for testbit (faster code) does not work for
  3. // all types, because of the fixed size of boolean and a subsequent
  4. // rangecheck error, hence compare to zero and with the correct type.
  5. Function TORDINALBITHELPER.ToBinString: string; inline;
  6. begin
  7.   Result:=BinStr(Self,SizeOf(TORDINALTYPE)*8);
  8. end;
  9.  
  10. Procedure TORDINALBITHELPER.SetBit(const index: TORDINALBITINDEX); inline;
  11. begin
  12.   TORDINAlUNSIGNEDTYPE(Self) := TORDINALUNSIGNEDTYPE(Self) or (TORDINALUNSIGNEDTYPE(1) shl index);
  13. end;
  14.  
  15. Procedure TORDINALBITHELPER.ClearBit(const index: TORDINALBITINDEX); inline;
  16. begin
  17.   TORDINALUNSIGNEDTYPE(Self):=TORDINALUNSIGNEDTYPE(Self) and not (TORDINALUNSIGNEDTYPE(1) shl index);
  18. end;
  19.  
  20. Procedure TORDINALBITHELPER.ToggleBit(const index: TORDINALBITINDEX); inline;
  21. begin
  22.   TORDINALUNSIGNEDTYPE(Self) := TORDINALUNSIGNEDTYPE(Self) xor (TORDINALUNSIGNEDTYPE(1) shl index);
  23. end;
  24.  
  25. Function TORDINALBITHELPER.TestBit(const Index: TORDINALBITINDEX):Boolean; inline;
  26. begin
  27.   Result := TORDINALUNSIGNEDTYPE(Self) and (TORDINALUNSIGNEDTYPE(1) shl index) <> 0;
  28. end;

Bart
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 10, 2019, 04:06:09 pm
Still all of that should have shown up in my tests (with trunk), but the unsigned solution is a good alternative.
One remark though, is that a ShortInt value anded with 128 (which is a unsigned byte value or wider and NOT a shortint value) is maybe propagated by the compiler to the next higher type... 128 is certainly not shortint.... It should be interpreted as 0 or expanded result..or a rangecheck error..
Second: is it possible that sysutils is compiled with {$R-} ? That would explain my tests.. (Will check that)
The suggested solution *should* not be necessary, since all overloads are well within the range for the type.
Did you check with a recent trunk? I still can't reproduce the issue, so may be only 3.0.4 and 3.2.0?

Anyway: the unsigned solution is not a matter of great importance to me, so I will apply it.

Thanks all for the help! It shows it is considered  useful  :)
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 10, 2019, 04:39:47 pm
Bart, the issue seems related to other versions than trunk:
Compile this with the real patch! It passes all tests too..
{$mode delphi}{$H+}{$rangechecks on}
uses sysutils;
var a:shortint = 0;
begin
  a.setbit(7);
  writeln(a);
end.

As well as any other types....

I will update the factored out version, though.
Title: Re: Some fun with bitmanipulations
Post by: garlar27 on October 10, 2019, 05:11:00 pm
Thaddy, did you see BitHelpers by Avra?

He was working on something similar.
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 10, 2019, 05:47:36 pm
Thaddy, did you see BitHelpers by Avra?

He was working on something similar.
Yes. I encouraged him even.

But this version can be integrated in the rtl.
Title: Re: Some fun with bitmanipulations
Post by: Bart on October 10, 2019, 08:21:21 pm
Hi Thaddy,

Attached a modified version of your original code (all bit manipulation is done with unsigned types).
Also an extensive test suite that tests all then methods you added for different bitness (even for 16-bit mode).
Its quite a bit more extensive than your test in the bugtracker.
It does all bit manipulation-methods (setbit, togglebit, clearbit, testbit) for all possible bits of a given type.

With my modifications the test program passes all tests.

When I have time, I will apply your last patch in the bugtracker to trunk and see if my tests pass.

Bart
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 10, 2019, 09:02:11 pm
Thanks Bart,
This looks good, but I also want to check why the original stuff failed. That is still not clear to me (128).
If I can test everything OK, I will submit your suggestions in a final patch. Again, thanks for the support.
Title: Re: Some fun with bitmanipulations
Post by: Bart on October 11, 2019, 12:16:48 am
See my notes and updated test-program in the bugtracker.

Bart
Title: Re: Some fun with bitmanipulations
Post by: valdir.marcos on October 11, 2019, 02:59:04 am
Just for reference:
0036146: PATCH extended ordinal helpers for bit patterns
https://bugs.freepascal.org/view.php?id=36146
Title: Re: Some fun with bitmanipulations
Post by: PascalDragon on October 11, 2019, 10:02:14 am
On Linux it's rather easy to test other platforms using QEMU's user space emulation (at least as long as you don't require any C libraries). The following is an example for m68k (it assumes the binutils are available as m68k-elf-*, in the $fpcdir is a directory testoutput and the test program is at $fpcdir/fpctests/tmyprogram.pp):

Code: [Select]
cd $fpcdir
make clean all BINUTILSPREFIX=m68k-elf- CROSSOPT=-Cpcfv4e
./compiler/pprcoss68k -n -Furtl/units/m68k-elf -XPm68k-elf- -FEtestoutput ./fpctests/tmyprogram.pp
qemu-m68k -cpu cfv4e ./testoutput/tmyprogram
(Note: untested, as I'm not on my development machine)

Even running the testsuite is possible with this using a script that is passed to the EMULATOR option of the makefile ;)
Title: Re: Some fun with bitmanipulations
Post by: MarkMLl on October 11, 2019, 03:48:57 pm
On Linux it's rather easy to test other platforms using QEMU's user space emulation (at least as long as you don't require any C libraries).

"Up to a point, Lord Copper" :-)

There's enough peculiarities in SPARC etc. relating to alignment and the extent to (and speed with) which the kernel handles alignment exceptions that relying on the Qemu maintainers' understanding of how real hardware will behave is probably unwise: it's yet another unknown in what usually turns out to be a complex set of equations.

And if it's really that easy why is https://bugs.freepascal.org/view.php?id=22696 still unfixed? :-) :-) :-) :-) :-)
Title: Re: Some fun with bitmanipulations
Post by: jamie on October 12, 2019, 01:33:54 am
You know, I always thought most of the basic lib files were synced between the 32 and 64 bit versions of Lazarus and fpc.. I guess I was wrong, again! >:(

  I just discovered that the helpers for the QWord and Int64 report 32 bit values when using the 64 bit Lazarus release 2.0.4 with Fpc 3.0.4

  This maybe the cause of many headaches when working with Helpers .

EDIT:
 Apparently this has been fixed in fpc 3.3.x

 How many more decades do we need to wait for this in Lazarus?

 I don't like using tools that change every other day.
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 12, 2019, 01:07:00 pm
Here's a new version based on - but not equal to - Bart's suggestions.

Note the bug regarding the size in 3.0.4 is a bug in Freepascal and this was fixed in 3.2.0 (32 vs 64 bit) and not part of the bugs in my code.
Note Bart's tests all pass. (Both with the patch and with the factored out helper as presented here)
Title: Re: Some fun with bitmanipulations
Post by: MarkMLl on October 14, 2019, 09:46:17 am
Should definitely be unsigned. You still need to be careful with 64-bit values if you go that high, since I believe they're stored internally as signed.

MarkMLl
Title: Re: Some fun with bitmanipulations
Post by: PascalDragon on October 14, 2019, 09:59:10 am
On Linux it's rather easy to test other platforms using QEMU's user space emulation (at least as long as you don't require any C libraries).

"Up to a point, Lord Copper" :-)

There's enough peculiarities in SPARC etc. relating to alignment and the extent to (and speed with) which the kernel handles alignment exceptions that relying on the Qemu maintainers' understanding of how real hardware will behave is probably unwise: it's yet another unknown in what usually turns out to be a complex set of equations.
It does not account for everything, yes, but in this case regarding endianess it would be plain Pascal programming errors anyway.
And at least for ARM it definitely helped to fix the alignment mess in the RTTI.

And if it's really that easy why is https://bugs.freepascal.org/view.php?id=22696 still unfixed? :-) :-) :-) :-) :-)
You even quoted the reason for this:
Quote
(at least as long as you don't require any C libraries)
For UI programs like lhelp you need to have all the required libraries available for the target platform. Fixing problems that are caught by FPC's testsuite is much easier. Though in this specific case one might be able to try the chm utility provided with FPC...
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 14, 2019, 10:01:47 am
I have submitted a new patch based on Michael's suggestions.
And indeed: all internal processing needs to be unsigned. (actually the signed/unsigned issue is only to represent the result)
The new patch passes all tests in all modes that support type helpers.
I will add a version for older than trunk later.
Title: Re: Some fun with bitmanipulations
Post by: Bart on October 14, 2019, 01:57:20 pm
I have submitted a new patch based on Michael's suggestions.
And indeed: all internal processing needs to be unsigned.

Wasn't that my suggestion?

Bart
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 14, 2019, 02:36:16 pm
Well, you have helped a lot, thank you!! but I rewrote the architecture on Michael's suggestion...
( the byte /word /integer part I already figured out.. You need word btw, not byte, to handle ordinals on current processors that handle up to 512 (exotics even more) per register and are just not yet implemented, same as current 64)

Anyway, the discussion made me rethink some parts in a fundamental way.
Title: Re: Some fun with bitmanipulations
Post by: Tz on October 14, 2019, 04:00:40 pm
What :o

this are more way seriously fun

Code: Pascal  [Select][+][-]
  1. program iso8583;  // https://en.wikipedia.org/wiki/ISO_8583
  2. {$mode objfpc}
  3. {$h+}
  4. uses SysUtils, OrdinalBits;
  5.  
  6. var
  7.   bitmap :QWord;
  8.   i :Integer;
  9.  
  10. begin
  11.  
  12.   bitmap := $2210001102C04804;
  13.   WriteLn(bitmap.ToHexString);
  14.  
  15.   for i:=63 downto 0 do
  16.     WriteLn('bit [',64-i,'] : ', bitmap.TestBit(i));
  17.  
  18. end.
  19.  

and toggle 512 exotic bulbs on or off ...

Awesome   :D :D :D
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 14, 2019, 04:14:18 pm
Well, testbit won't help you very much but setbit/clearbit and togglebit do... It was designed with electronics in mind.
And yes, you can toggle a lot on or of, you can even MMAP an appropriate value to a hardware control like GPIO.
Title: Re: Some fun with bitmanipulations
Post by: Tz on October 14, 2019, 04:43:01 pm
In ISO8583 TestBit is useful for determine existence of secondary bitmap. 
TestBit(1) in primary bitmap (or 63 in your helper) if true, there must be a secondary bitmap.

Master and Visa are serious and you make programming fun, :D
such ethos are less found today, in my place.

Excellent Thaddy,  and Thank you all for this forum,  so many ideas here.

Title: Re: Some fun with bitmanipulations
Post by: garlar27 on October 14, 2019, 05:29:05 pm
In ISO8583 TestBit is useful for determine existence of secondary bitmap. 
TestBit(1) in primary bitmap (or 63 in your helper) if true, there must be a secondary bitmap.

Master and Visa are serious and you make programming fun, :D
such ethos are less found today, in my place.

Excellent Thaddy,  and Thank you all for this forum,  so many ideas here.


Yeah!!!

I know what you mean Tz, I once had to do it the hard way !!!

And managed everything in strings of '0' and '1' fearing problems with endianness.
Title: Re: Some fun with bitmanipulations
Post by: jamie on October 14, 2019, 05:41:37 pm
I haven't looked at the implementation of the bit setting code but I hope it's inline because I hate unused lard in my EXE 's  >:(
Title: Re: Some fun with bitmanipulations
Post by: Tz on October 15, 2019, 03:20:15 pm
garlar27  :D

couting finger may be? or check missing tooth?  :D

But this is real word protocol  https://en.wikipedia.org/wiki/Modbus

We can read or wite a coil,  and some enhancement we can read Octal, Nibble, Byte like SubBit(1, 2) = Value 0 - 3

example from digital input device 16 bit register

Name                    Min  Max   Bits/Sign
Unnamed digital input 1 0    15    13/16-16/16
Unnamed digital input 2 0    15    9/16-12/16
Unnamed digital input 3 0    15    5/16-8/16
Unnamed digital input 4 0    15    1/16-4/16


if Thaddy dont mind  :D

Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 15, 2019, 04:34:02 pm
I haven't looked at the implementation of the bit setting code but I hope it's inline because I hate unused lard in my EXE 's  >:(
Of course it is inlined  :D And they are straight C function translations (Oops... :( ) from literature by Dennis Richie... O:-)
(True, but a bit kidding: it is very simple Boolean logic)
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 15, 2019, 04:39:24 pm
@Tz
Yes, you can use that. I had hardware in mind.
If you know the memory hardware interface start address, you can fpmmap that address and use the helpers.
I  have a new version (on the bug tracker) that verifies if any of the operations actually succeeded.
Will add that here too.
Title: Re: Some fun with bitmanipulations
Post by: garlar27 on October 15, 2019, 05:51:20 pm
couting finger may be? or check missing tooth?  :D
Yeah !!! Something like that LOL  :D

I don't remember well exactly what I did since many years has passed from that day (I was using Laz 0.9.2 I think). I recall having trouble to convert the the received bitmap string and the BCD string to anything useful, so I did what I could (cast every char to byte then convert it to a binary string or something like that and being careful with the endiannes). Whatever I did back then worked well against the testing server but I wasn't happy....  :-[
Title: Re: Some fun with bitmanipulations
Post by: Thaddy on October 15, 2019, 05:57:42 pm
couting finger may be? or check missing tooth?  :D
Yeah !!! Something like that LOL  :D
Well the fingers were never an issue, but the teeth are now perfectly fine: I can even borrow them to you  if you need them %).
Title: Re: Some fun with bitmanipulations
Post by: Tz on November 17, 2019, 05:59:26 am
@garlar27  I am using char >= '8'   %)    :)

@Thaddy thank you

how about BitSize, LSB, and MSB, so we can make pattern for disco bulbs   :D

for i := int.LSB to int.MSB do 
  process and or xor not bit

Title: Re: Some fun with bitmanipulations
Post by: Thaddy on November 17, 2019, 08:35:16 am
Well, the version in trunk has Ordinal bit index types, e.g. for byte TByteBitIndex etc.
And we already have Hi() Lo() intrinsics but MSB/LSB can be like so:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$H+}
  2. // needs trunk
  3. uses sysutils;
  4. const
  5.   LSB_word = 0;
  6.   MSB_word = High(TWordBitIndex);
  7. var
  8.   bits:TWordBitIndex;
  9.   test:word = %1010101010101010;
  10. begin
  11.   writeln('%',test.ToBinString);
  12.   for Bits := LSB_word to MSB_word do test.ToggleBit(bits);
  13.   writeln('%',test.ToBinString);
  14. end.

A small example (for Arduino):
Code: Pascal  [Select][+][-]
  1. var
  2.   LEDPort: byte absolute PortA; // mapped hardware
  3.  
  4. const
  5.   LEDPin = 3;
  6. { old code from wiki
  7. implementation
  8.   LEDPort:= LEDPort or (1 shl LEDPin); //LED=on}
  9. { New code with trunk);}
  10.   LedPort.SetBit(LEDPin); // LED=on
See https://wiki.freepascal.org/AVR_Programming
The extensions were written with hardware in mind.
TinyPortal © 2005-2018