bit-aligned read & write

General FreeBASIC programming questions.
dafhi
Posts: 1640
Joined: Jun 04, 2005 9:51

bit-aligned read & write

Post by dafhi »

added comments as per feedback
greatly simplified

(former project name: packed bits)

Code: Select all

/' -- bit-aligned read / write (up to 57 bits) - 2024 Feb 29

    Why 57 ?
  
  internal var b_offs can maximally represent an offset of 7:
  00000001
  
  that bit plus up to 7 more bytes = 57 bits
 
   - dafhi
  --------
  
   updates documented at their locality

'/


''
'' -- bits printout .. MSB left
''
function sbin(p as any ptr, cBits as longint = 1) as string
  
  static as string  ret:  ret = "" '' 2024 Feb 25
  dim as long       cbytes = (cbits + 7) \ 8
  dim as ubyte ptr  b = p + cbytes - 1  
  
  for j as long = 1 to cBytes
    var s = ""
    for i as long = 7 to 0 step -1
      s += str((*b shr i) and 1)
    next
    ret += s + " "
    b -= 1
  next
  return ret
  
end function


#define min( a, b)        iif( (a)<(b), (a), (b) )
#define max( a, b)        iif( (a)>(b), (a), (b) )

'' reduced text
#define dbl         as double

function clamp( in dbl, hi dbl = 1, lo dbl = 0) dbl
  return min( max(in, lo), hi ) '' 2023 June 12
End Function


' -- support
'
union uptrs           '' i forget who suggested (avoids sus ptr)
  as any ptr          a
  as ubyte ptr        b
  as ushort ptr       sho
  as ulong ptr        l
  as ulongint ptr     li
  As Single Ptr       s
  as double ptr       d
End Union


  namespace ba57 ' bit aligned read / write - 2024 Feb 29 - by dafhi
  
  /' -- usage
  
  dim as byte  a(5)
  ba57.pdata = @a(0)
  ba57.wri valu, offs, cbits_0_to_57
    var result = _
  ba57.rea( offs, cbits_0_to_57 )
'/

  '' support
  dim as any ptr    pdata

  dim as ulongint   b_offs, mask
  
  dim as uptrs      gp

  sub _rw_common( bpos as ulongint, byref c as byte )
    gp.a   = pdata + bpos \ 8 '' integer divide
    b_offs = bpos - (bpos \ 8) * 8
    c      = clamp( c, 57 )
    mask = ( (1 shl c)-1 ) shl b_offs
    'mask = ((culngint(1) shl c)-1) shl b_offs  ' Feb 29
  end sub

'' main functions
''
function rea( bitpos as ulongint, cbits as byte = 1 ) as ulongint
  _rw_common bitpos, cbits
  return (*gp.li and mask)shr b_offs
end function

sub wri( valu as ulongint, bitpos as ulongint, cbits as byte = 1 )
  _rw_common bitpos, cbits
  *gp.li xor= *gp.li and mask
  *gp.li or= (valu shl b_offs)and mask
end sub

end namespace



''
'' Main
''
dim as ulongint a
ba57.pdata = @a

print " bit-aligned read / write"
print

print " wri"

var valu = -1
var offs = 7
var size = 2
ba57.wri valu, offs, size

'var data_size_in_bits = 5 * 8  ' Feb 29
var print_size_in_bits = 5 * 8
print sbin( @a, print_size_in_bits )

print " rea"

var result = ba57.rea( offs, print_size_in_bits - offs )

print sbin( @result, print_size_in_bits );
print " (from bit"; offs; ")"
Last edited by dafhi on Feb 29, 2024 9:49, edited 17 times in total.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: packed bits

Post by deltarho[1859] »

Comments are all very well but expand your preamble to give folk a clue what your code is for, otherwise you may get a few views but no responses; which is what you asked for. Image
xbgtc
Posts: 249
Joined: Oct 14, 2007 5:40
Location: Australia

Re: packed bits

Post by xbgtc »

deltarho[1859] wrote:expand your preamble to give folk a clue what your code is forImage
+1
There are far too many posts like this where you have no idea what the code is for nor what it's supposed to do or even how to use it.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: packed bits

Post by deltarho[1859] »

If we hover over 'Tips and Tricks', this sub forum, it says “Post your FreeBASIC tips and tricks here. Please don't post your code without including an explanation.”

I cannot remember who, but counting_pine got quite cross at someone who habitually posted code without an explanation. If I was a moderator, knick named the 'Grim Reaper' with just cause, I would give offending authors five days to 'knock out a decent preamble' to avoid the thread being deleted. Image
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: packed bits

Post by jj2007 »

dafhi wrote:hasn't been well tested. feedback and bug reports welcome

[update 2: ...
What makes you think that you can just ignore deltarho's suggestion?
Besides, if it hasn't been well tested, why do you put it in the Tips & Tricks section?
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: packed bits

Post by deltarho[1859] »

jj2007 wrote:Besides, if it hasn't been well tested, why do you put it in the Tips & Tricks section?
Good question.

I think that this thread should be moved to the 'Recycle Bin' sub forum. Oh wait, there isn't one. Image
Imortis
Moderator
Posts: 1923
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: packed bits

Post by Imortis »

dafhi wrote:hasn't been well tested. feedback and bug reports welcome

[update 2: reduced a 'private' variable size to byte, small comments changes]

Code: Select all

/' -- packed bits 2021 Sep 7 - by dafhi

  bit-aligned properties w/ example
  
  [update]
  
  changed ns_packbuts.t._cbits to ubyte, and t Field = 1
  adjusted a few comments

'/


#define def #define

def     decl  declare
def     prop  property
def     csr   constructor

def min( a, b)        iif( (a)<(b), (a), (b) )
def max( a, b)        iif( (a)>(b), (a), (b) )

union suspicion_suppressor   ' suspicious ptr tango
  as any ptr          a
  as ubyte ptr        b
  as ushort ptr       sho
  as ulong ptr        l
  as ulongint ptr     li
  As Single Ptr       s
  as double ptr       d
End Union


dim shared as suspicion_suppressor  gp
 
 
 
  namespace ns_packbits

type          return_type as ulong  '' manually adjust:  no higher than 32 bit
type          extended_type as ulongint '' manually adjust:  2x base type size


dim as long       bit0, b_offs, byt0
const             lenx8 = len(return_type) * 8

dim as long       gcbits '' tracks cumulative bits


type t field = 1  '' byte align

  decl            csr( cbits as long = 1, reset as long = false)  '' constructor
 
  decl prop       cbits( as ubyte)
  decl prop       cbits as ubyte
  decl prop       bytes_req( c_elems as longint) as longint  ' aka. byte array size
 
  decl function   val_in( as any ptr, as long) as return_type
  decl sub        val_out( as any ptr, as long, as longint = -1)
  decl sub        reset_global_offset
 
  decl prop       mask as return_type
  decl prop       pow2 as extended_type
 
  decl sub        _array_ptr_and_pos0( as any ptr, as long)
 
  as return_type  _valu
  as ulong        _offset '' downstream udt may have millions of members
  as ubyte        _cbits
End Type

csr t( _cbits as long, reset as long = false)
  gcbits += gcbits * reset
  cbits = _cbits      ' cbits property
end csr

prop t.cbits( i as ubyte)
  _cbits = min(i, lenx8)
  _offset = gcbits
  gcbits += _cbits
end prop

prop t.cbits as ubyte
  return _cbits
end prop

sub t.reset_global_offset
  gcbits = 0
end sub

prop t.bytes_req( c_elements as longint) as longint
  return 1 + (_cbits + _offset) * c_elements \ 8 ' integer div
end prop

prop t.pow2 as extended_type
  return mask + 1
end prop

prop t.mask as return_type
  return (2^_cbits) - 1
end prop

sub t._array_ptr_and_pos0( p as any ptr, idx as long)
  bit0 = idx * gcbits + _offset
  byt0 = bit0 \ 8   ' integer div
  b_offs = bit0 - byt0 * 8
  gp.a = p + byt0   ' gp is global pointer union
end sub

sub t.val_out( p as any ptr, idx as long, _val as longint)
  _valu -= (_val - _valu) * (_val > -1) '' more cpu friendly than if statement
  _array_ptr_and_pos0 p, idx
  *gp.li or= mask shl b_offs              '' zero out dest bits
  *gp.li xor= mask shl b_offs
  *gp.li or= (_valu and mask) shl b_offs  '' array write
end sub

function t.val_in( p as any ptr, idx as long) as return_type
  _array_ptr_and_pos0 p, idx
  _valu = (*gp.li shr b_offs) and mask
  return _valu
end function

end namespace ' --- ns_packbits


'' debugger
function strBin(p as any ptr, cBytes as longint = 1) as string
  var s = ""
  gp.a = p + cbytes - 1
  for j as longint = 1 to cBytes
    for i as long = 7 to 0 step -1
      s += str((*gp.b shr i) and 1)
    next:  gp.a -= 1
  next
  return s
end function


'
' code sample Main
'
 
  namespace ns_myEntity '' namespace the entire universe!

using ns_packbits

dim as t eye_color = type(2, true) '' bit count, reset_global_offset
dim as t hero = type(1)

function byte_array_size( player_count as longint = 10) as longint
  return hero.bytes_req( player_count ) '' last-in-line ns_packbits.t
end function

end namespace



screenres 800, 600

var player_count = 10
var u = player_count - 1
? "player count"; u + 1
?

using ns_myEntity

var           ub = byte_array_size(player_count) - 1
dim as ubyte  a(ub)

? "byte count"; ub + 1

for i as long = 0 to u
  eye_color.val_out @a(0), i, i mod eye_color.pow2
  hero.val_out @a(0), i, 1
next

? "bits: "; strbin( @a(0), ub + 1)
?: ?
? "eye col", "hero"
?

for i as long = 0 to u
  ? eye_color.val_in( @a(0), i),
  ? hero.val_in( @a(0), i)
next

sleep
While you do have comments in your code at the top, where it's visible for all to see in the first post, it is not exactly descriptive.

You do, however, have example of how to use it. They are in the same code block at the bottom.

A better description of what this is supposed to do and why you would want to use it is not a bad idea. You should not put untested code here, though. I will move the thread from Tips & Tricks to General.
xbgtc
Posts: 249
Joined: Oct 14, 2007 5:40
Location: Australia

Re: packed bits

Post by xbgtc »

deltarho[1859] wrote:If we hover over 'Tips and Tricks', this sub forum, it says “Post your FreeBASIC tips and tricks here. Please don't post your code without including an explanation.”

I cannot remember who, but counting_pine got quite cross at someone who habitually posted code without an explanation. If I was a moderator, knick named the 'Grim Reaper' with just cause, I would give offending authors five days to 'knock out a decent preamble' to avoid the thread being deleted. Image
Haha but yeh and it's not just 'Tips and Tricks' but other sections as well. I have lost count of the number of times i've seen program code posted that looks interesting but just did not know what it's supposed to do or how to use it so just didn't worry about it :)
dafhi
Posts: 1640
Joined: Jun 04, 2005 9:51

Re: packed bits

Post by dafhi »

sorry guys i've been away. i come back and there's a small explosion of comments.

well i've updated the code which should hopefully be clearer
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: packed bits

Post by deltarho[1859] »

Here is a simple tip: The more complex our code is the more 'dumbing down' we need to employ in our description to get others to understand it.

To my mind, dafhi, your opening post is still as clear as mud.
xbgtc wrote:but just did not know what it's supposed to do or how to use it so just didn't worry about it :)
Code posters should bear that in mind.

A paradox: A poor description leads to poor feedback. A good description leads to poor feedback.

The second case is also true because it does not leave the reader wanting.

My preambles are probably the longest in this forum. The aim is to reach the widest audience. If code posters fail to do that, then my advice to them is not to bother to post code.
Imortis
Moderator
Posts: 1923
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: packed bits

Post by Imortis »

deltarho[1859] wrote:A paradox: A poor description leads to poor feedback. A good description leads to poor feedback.
I once read an article from a UI designer where he talked about a problem users kept having because they didn't understand what an error meant. So he kept changing the error description to be more detailed and the problem just kept getting worse. His conclusion was this: the more text that is on the screen, the less chance there is that anyone will read it all.

It seems that there's a sweet spot. Too much detail and it is ignored. Not enough and no one understands it.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: packed bits

Post by jj2007 »

deltarho[1859] wrote:To my mind, dafhi, your opening post is still as clear as mud.
Indeed. I have a vague suspicion that he wants some flag setting & reading, as in this pseudocode snippet:

Code: Select all

  FileIsDirty = 15		; define a name for the bit(0...31)

  SetFlags FileIsDirty, 1

  .if Flags(FileIsDirty)
	Print "This file is dirty"
  .else
	Print "This file has been saved"
  .endif
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: packed bits

Post by deltarho[1859] »

Imortis wrote:Too much detail and it is ignored.
So, we should make it entertaining, reducing the likelihood of someone 'pulling out' early. We should also write to exercise the reader's imagination. They will continue reading in the hope of being inspired even further.

In other words, we should 'sell' our code.

If we don't 'sell' our code, far less will 'buy' it.

I find that blatantly obvious.
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: packed bits

Post by Munair »

I'm amazed to see that someone who joined in 2005 throws a code snippet on the forum without any description, and initially on Tips and Tricks no less. But regardless, code shouldn't be dumped like that for users to figure out what it does. I for one, quickly skimmed over the code and immediately lost interest due to lack of any decent description or comments. Reading the documentation on mki/cvi and friends is a lot more appealing in this regard.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: packed bits

Post by fxm »

Anyway, I think it's not the moderator's job to add a description of the code when it's missing !
Post Reply