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,117 of 243,242   
   Keith Thompson to David Brown   
   Re: _BitInt(N)   
   24 Nov 25 17:23:47   
   
   From: Keith.S.Thompson+u@gmail.com   
      
   David Brown  writes:   
   > On 24/11/2025 12:17, bart wrote:   
   >> On 24/11/2025 09:29, David Brown wrote:   
   [...]   
   > So if you want the full range of values of x and y to be usable here,   
   > then NM would have to be N * M.  But you would also need a cast, such   
   > as "_BitInt(NM) z = (_BitInt(NM)) x * y;", just as you do if you want   
   > to multiply two 32-bit ints as a 64-bit operation.   
      
   N + M, not N * M.   
      
   > Alternatively, you might know more about the values that might be in x   
   > and y, and have a smaller NM (though you still need a cast if it is   
   > greater than both N and M).  Or you might be using unsigned types and   
   > want the wrapping / masking behaviour.   
   >   
   > The point was not what size NM is, but that it is known to the   
   > compiler at the time of writing the expression.   
   >   
   >> It sounds like the max precision you get will be the latter.   
   >>   
   >>> can be implemented as something like :   
   >>>   
   >>>      __bit_int_signed_mult(NM, (unsigned char *) &z,   
   >>>              N, (const unsigned char *) &x,   
   >>>              M, (const unsigned char *) &y);   
   >>>   
   >>>   
   >> How would you write a generic user function that operates on any   
   >> size BitInt? For example:   
   >>     _BitInt(?) bi_square(_BitInt(?));   
   >>   
   >   
   > You can't.  _BitInt(N) and _BitInt(M) are distinct types, for   
   > differing N and M.  You can't write a generic user function in C that   
   > implements "T foo(T)" where T can be "int", "short", "long int", or   
   > other types.  C simply does not have type-generic functions.   
      
   Sort of.  C23 defines the term "generic function" (N3220 7.26.5.1,   
   string search functions).  For example, strchr() can take a const void*   
   argument and return a const void* result, or it can take a void*   
   argument and return a void* result.  (C++ does this by having two   
   overloaded strchr() functions.)   
      
   These "generic functions" are (almost certainly) implemented as macros   
   that use _Generic.  If you bypass the macro definition, you get the   
   function that can take a const char* and return a char*.   
      
   So C doesn't have type-generic functions, but it does have feature that   
   let you implement things that act like type-generic functions.   
      
   > You /can/ write generic macros that handle different _BitInt types,   
   > but that would quickly get painful given that you'd need a case for   
   > each size of _BitInt you wanted for the _Generic macro.   
      
   Indeed.  A _Generic selection that handles all the ordinary non-extended   
   integer types needs to handle 12 cases if I'm counting correctly, which   
   is feasible.  But the addition of bit-precise types adds   
   BITINT_MAXWIDTH*2-1 new distinct predefined types, and a generic   
   selection would need one case for each.   
      
   However, you could have a function that takes a void*, a size, and a   
   width as arguments and operates on a _BitInt(?) or unsigned _BitInt(?)   
   type.  In fact, gcc has internal functions like that for multiplication   
   and division.  (You mentioned something like that in text that I've   
   snipped.)   
      
   [...]   
      
   >> This assumes BitInts are passed and returned by value, but even   
   >> using BitInt* wouldn't help.   
   >   
   > Yes, they are passed around as values - they are integer types and are   
   > passed around like other integer types.  (Implementations may use   
   > stack blocks and pointers for passing the values around if they are   
   > too big for registers, just as implementations can do with any value   
   > type. That's an implementation detail - logically, they are passed and   
   > returned as values.)   
      
   Yes, and in general a _BitInt argument has to be copied to the   
   corresponding parameter, since a change to the parameter can't affect   
   the value of the argument.   
      
   But passing huge _BitInts by value is no more problematic than passing   
   huge structs by value.   
      
   [...]   
      
   --   
   Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com   
   void Void(void) { Void(); } /* The recursive call of the void */   
      
   --- 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