Path: csiph.com!weretis.net!feeder9.news.weretis.net!border-1.nntp.ord.giganews.com!border-4.nntp.ord.giganews.com!nntp.giganews.com!eternal-september.org!feeder.eternal-september.org!nntp.eternal-september.org!eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: _BitInt(N) Date: Tue, 25 Nov 2025 19:06:31 -0800 Organization: None to speak of Lines: 171 Message-ID: <87tsyhcx1k.fsf@example.invalid> References: <10dajlh$ko3c$1@dont-email.me> <10fus62$hl69$1@solani.org> <10fv2dm$3can9$1@paganini.bofh.team> <10fv40v$1f7a2$1@dont-email.me> <87ms4c4bom.fsf@example.invalid> <10g08vm$1us25$1@dont-email.me> <10g1et7$2bmus$1@dont-email.me> <10g1j7h$2deh9$1@dont-email.me> <10g1qq9$2f8lb$4@dont-email.me> <10g28gm$2mf9s$1@dont-email.me> <10g2f2d$2oufq$1@dont-email.me> <10g2m3v$2s5sa$1@dont-email.me> <10g53au$3onvh$1@dont-email.me> <10g58pa$3r273$1@dont-email.me> <877bvdk8c4.fsf@example.invalid> <10g5ne5$4i3$1@dont-email.me> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Date: Wed, 26 Nov 2025 03:06:36 +0000 (UTC) Injection-Info: dont-email.me; posting-host="6f47bd7264b2dbdf6e6603756425bf4b"; logging-data="38863"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+8/+wh+m21V5sXECslFdn3" User-Agent: Gnus/5.13 (Gnus v5.13) Cancel-Lock: sha1:zXNiHBFBUImeVdnM7cC6l467lK4= sha1:NbZH5GNJAFvUumR8Y7xZS4vmu/E= Xref: csiph.com comp.lang.c:395487 bart writes: > On 25/11/2025 23:20, Keith Thompson wrote: >> bart writes: >>> On 25/11/2025 20:25, David Brown wrote: >> [...] >>>>   Arbitrary sized integers are a very different kettle of fish from >>>> large fixed-size integers, and are not something that would fit in >>>> the C language - they need a library. >>> >>> Really? I wouldn't have thought there was any appreciable difference >>> between the code for multiplying two 100,000-bit BitInts, and that for >>> multiplying two abitrary-precision ints that happen to be 100,000 >>> bits. >> It's not about the code that implements multiplication. In gcc, >> that's done by calling a built-in function that can operate on >> arbitrary data widths. Think about memory management. > > Well, I was responding to a suggestion that BitInt support didn't need > a library. David didn't actually suggest that. He said that arbitrary-sized integers would need a library (and such libraries exist), not that fixed-size integers don't. The point, I think, is that arbitrary-sized integers, without radical changes to the language, would require a *visible* library while the _BitInt types are built into the language. Yes, some operations are implemented as function calls in some implementations. The same could be true for just about any operation. Some implementations have software floating-point. gcc implements a large struct assignment by generating a call to memcmp. And so on. > But memory management is a good point. Actual, variable-sized bigints > would be awkward in C if you want to use them in ordinary expressions. > > Although managing large fixed-sized types, which may also involve > intermediate, transient values, can have their own problems. Again, any such problems have already been solved by the gcc and llvm/clang implementations (aside from a clang problem with large multiplication and division). "This feature would be too difficult to implement" is a weak argument when implentations already exist. BTW, clang has had this feature (originally called _ExtInt rather than _BitInt) since 2019. Here's the git log entry. The committer is one of the authors of the N2021 paper, so the similarities are unsurprising. ``` commit 61ba1481e200b5b35baa81ffcff81acb678e8508 Author: Erich Keane Date: 2019-12-24 07:28:40 -0800 Implement _ExtInt as an extended int type specifier. Introduction/Motivation: LLVM-IR supports integers of non-power-of-2 bitwidth, in the iN syntax. Integers of non-power-of-two aren't particularly interesting or useful on most hardware, so much so that no language in Clang has been motivated to expose it before. However, in the case of FPGA hardware normal integer types where the full bitwidth isn't used, is extremely wasteful and has severe performance/space concerns. Because of this, Intel has introduced this functionality in the High Level Synthesis compiler[0] under the name "Arbitrary Precision Integer" (ap_int for short). This has been extremely useful and effective for our users, permitting them to optimize their storage and operation space on an architecture where both can be extremely expensive. We are proposing upstreaming a more palatable version of this to the community, in the form of this proposal and accompanying patch. We are proposing the syntax _ExtInt(N). We intend to propose this to the WG14 committee[1], and the underscore-capital seems like the active direction for a WG14 paper's acceptance. An alternative that Richard Smith suggested on the initial review was __int(N), however we believe that is much less acceptable by WG14. We considered _Int, however _Int is used as an identifier in libstdc++ and there is no good way to fall back to an identifier (since _Int(5) is indistinguishable from an unnamed initializer of a template type named _Int). [0]https://www.intel.com/content/www/us/en/software/programmable/quartus-prime/hls-compiler.html) [1]http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2472.pdf Differential Revision: https://reviews.llvm.org/D73967 ``` [...] > I think I would have responded better to BitInt if presented as a > 'bit-set', effectively a fixed-size bit-array, but passed by > value. This is something that I'd considered myself at one time. > > Those would have logical operators, access to indvidual bits, but not > arithmetic nor shifts, and no notion of twos complement. (In my > implementation, they could also have been initialised like Pascal > bitsets.) So rather than a new feature for wide integer types, you would have preferred something that DOESN'T SUPPORT ARITHMETIC?? How is that relevant to _BitInt? Bit vectors are great, but they aren't integers. This might interest you : https://github.com/michaeldipperstein/bitarray > More significantly, an unbounded version could be passed by reference, > with an accompanying length (I could also use slices that have the > length) as happens with arrays in C. Right, like arrays of unsigned char. [...] >> It could also be nice to be able to write code that deals with >> multiple widths of _BitInt types, as we can do for arrays even >> without VLAs. But C's treatment of arrays is messy, and I'm not >> sure duplicating that mess for _BitInt types would be a great idea. >> And I wouldn't want to lose the ability to pass _BitInt values >> to functions. >> [...] >> >>> So, a better fit for a struct then? Here I'm curious as to what >>> BitInt(128) brings to the table. >> It brings a 128-bit integer type with constants and straightforward >> assignment, comparison, and arithmetic operators. > > I was commenting on the ipv6 example, where structs give you that > already, except arithmetic which makes little sense. OK, I probably snipped too much context here. unsigned _BitInt(128) could be a reasonable way to represent an ipv6 address. So could unsigned char[16], or a struct containing an unsigned char[16]. [...] >>> At least, I've been able to add to my collection of C types that >>> represent an 8-bit byte: >>> >>> signed char >>> unsigned char >>> int8_t >>> uint8_t >>> _BitInt(8) >>> unsigned _BitInt(8) >>> >>> The last two are apparently incompatible with the char versions. >> You forgot plain char, > > I had char but took it out, as it's a outlier. OK, whatever works for you. >> int_least8_t, and uint_least8_t. > > And 'fast' versions? I still don't know what any of these mean! No > other languages seem to have bothered. The "fast" versions could be larger than 8 bits (though I'm mildly surprised to see that [u]int8_fast_t types *are* 8 bits on several compilers I just tried). Of course C++ and Objective-C incorporate C's standard library. You say you don't know what they mean. Do you *want* to know? You can always read the standard's description if you're curious. I never assume that saying you don't know something means that you want to know about it. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com void Void(void) { Void(); } /* The recursive call of the void */