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