home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c      Meh, in C you gotta define EVERYTHING      243,242 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 242,082 of 243,242   
   bart to David Brown   
   Re: _BitInt(N)   
   24 Nov 25 12:31:44   
   
   From: bc@freeuk.com   
      
   On 24/11/2025 11:17, David Brown wrote:   
   > On 24/11/2025 01:30, bart wrote:   
      
   >> Saving memory was mentioned. To achieve that means having bitfields   
   >> that may not start at bit 0 of a byte, and may cross byte- or word-   
   >> boundaries.   
   >>   
   >   
   > No, that is incorrect.   
   >   
   > The proposal mentions saving /space/ as relevant in FPGAs - not saving /   
   > memory/.   
      
   But I was responding to a suggestion here that one use of _BitInts -   
   presumably for ordinary hardware - was to save memory.   
      
   That's not going to happen if they are simply rounded up to the next   
   power-of-two type.   
      
   If the purpose is, say, a 17-bit type that wraps past values of 131071,   
   then that sounds like a lot of extra code needed, for something that   
   does not sound that useful. Why modulo 2**17; why not 100,000? Or any   
   value more relevant to the task.   
      
      
   >  The authors use-case here is in writing code that can be   
   > compiled with a "normal" C compiler on a "normal" target, and also   
   > compiled to FPGA /hardware/, with the same semantics.  In hardware, a 5-   
   > bit by 5-bit single-cycle multiplier is very much smaller than an 8-bit   
   > by 8-bit multiplier, and orders of magnitude smaller than if the 5-bit   
   > integers are promoted to 32-bit before multiplying.   
   >   
   > The proposal is not about saving /memory/.  It specifically says that a   
   > _BitInt(N) has the same size and alignment as the smallest basic type   
   > that can contain it, until you get to N greater than 64-bit, in which   
   > they are contained in an array of int64_t.  (The reality is a little   
   > more formal, to handle targets that have other sizes of their basic types.)   
   >   
   > So on a "normal" target, a _BitInt(3) is the same size and alignment as   
   > a uint8_t, a _BitInt(35) is effectively contained in an uint64_t, and an   
   > array of 4 _BitInt(17) on a 32-bit system will take 16 bytes or 128   
   > bits, not 68 bits.   
      
   > As far as I can see, the C23 standard does not specify these details,   
   > and leaves them up to the target ABI.  But at the very least, they will   
   > always take an integer number of bytes - unsigned char.  There can never   
   > be any crossing of byte boundaries.   
      
   What about arrays of _BitInt(1), _BitInt(2) and _BitInt(4)? These could   
   actually be practically implemented, with a few restrictions, and could   
   save a lot of memory.   
      
   > Why?  And why do you talk specifically about odd numbers?  I can   
   > understand your concern about packing arrays of _BitInts that are not   
   > multiples of 8, though I hope you now understand that it is not the   
   > problem you thought it was.  However, I see no reason to suppose that   
   > _BitInt(5) is any more or less "complicated" than _BitInt(6) just   
   > because 5 is an odd number!   
      
   I mean odd compared with powers-of-two, or multiples of 8.   
      
   >   
   > A major point of the _BitInt concept is to be able to specify and use   
   > integers of specific explicit sizes in a way that is as implementation   
   > independent as possible.  Some aspects of the implementation cannot be   
   > avoided - such as the size of unsigned char and alignment and padding   
   > for storage.  But the behaviour of the types is entirely independent of   
   > the implementation.  There are no "extra rules" - neither for specific   
   > implementations, nor for specific sizes of _BitInt's.   
   >   
   > Efficiency of implementation is, of course, up to the implementation.   
   > But there is absolutely no reason to suppose that working with a _BitInt   
   > of size up to the implementation's maximum integer type is going to be   
   > less efficient than using other types and masking.  For larger   
   > _BitInt's, there are different possible implementation strategies with   
   > different pros and cons in regard to efficiency.   
   >   
   >>   
   >> What happens when a 391-bit type, even unsigned, overflows? These   
   >> larger types are likely to use a multiple of 64-bits, and for 391 bits   
   >> will need 7 x 64 bits, of which the last word will have 57 bits of   
   >> padding. It's very messy.   
   >>   
   >   
   > It is not messy at all.  Signed integer overflow is UB, unsigned integer   
   > overflow is wrapping.  It's the same as always, and could not be   
   > simpler, clearer or neater.   
      
   In my 391-bit example, the top 7 bits will be within a 64-bit word. What   
   values will those extra 57 bits be?   
      
   Taking just those 7 bits by themselves, if the value is 1111111, that is:   
      00000000'00000000'00000000'00000000'00000000'00000000'00000000'01111111)   
      
   and you do an arithmetic right shift, then you will get 0111111 not   
      
   1111111, since the hardware sign bit is bit 63 not bit 6. It needs more   
   work.   
      
      
   >> Such limits for /fixed-width/ integers are ridiculous.   
   >   
   > Um, I think you might want to re-read and re-phrase that.  When you have   
   > fixed-width integers, you have a finite range.   
      
   No, I stand by it. There are even different levels of ridiculousness:   
   expecting a language to support a huge fixed integer type like   
   int1000000_t (when C only acquired 8/16/32/64-bit types in C99, and   
   those still aren't built-in).   
      
   And allowing random sizes such as int817838_t. (See, it seems much   
   sillier using this syntax!)   
      
   For such sizes it makes much more sense to acknowledge the existence of   
   arbitrary-precision support, so that the equivalents of int1000000_t and   
   int817838_t would be compatible types. Or you can forget specific widths   
   and just have the one bigint type.   
      
   (I use such types, but within a library, and there there are ways cap   
   the precision.)   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca