On Wed, Oct 15, 2025 at 03:30:11PM +0200, Alejandro Colomar wrote:
> Hi Michael,
> 
> On Wed, Oct 15, 2025 at 02:47:46PM +0200, Michael Matz wrote:
> > Hello,
> > 
> > On Tue, 14 Oct 2025, Alejandro Colomar wrote:
> > 
> > > Because bool is entirely different from the other regular integer types,
> > > and has entirely different rules,
> > 
> > Why do you say that?  bool and its operations is a normal finite algebra 
> > on an ordered set, the only thing being that its add/mul are saturating 
> > and have "funny" colloquial names (namely "or" and "and"):
> > 
> >   add == or ; mul == and
> 
> Saturating arithmetics are what make it different, IMO.
> 
> > Because the set is finite and fully ordered comparison makes (a) sense, 
> > and the (b) max/min exists; and because it is so very small these two 
> > operations actually coincide with add and mul as well: max == or and 
> > min == and.  The maxof/minof of that type is again trivial as well, and 
> > arguably even more elegantly defined than on the other integer types 
> > (because of the saturating behaviour of add, that maxof is the fixed-point 
> > of the operation add1, and minof the fixed point of mul-any).
> 
> I agree it would make perfect sense to define _Maxof and _Minof with
> bool.  It is clear that _Maxof(bool)==true and _Minof(bool)==false;
> I don't think anyone would be surprised by that.  However, I doubt the
> usefulness of that.
> 
> Here are all the uses of these operators in the shadow utils project
> (of course, implemented as macros with the usual bit shifts):
> 
>       alx@devuan:~/src/shadow/shadow/master$ grep -rh -C2 'type_m' lib* src/ 
> | grep -v ^$
>       #define str2i(T, ...)  a2i(T, __VA_ARGS__, NULL, 0, type_min(T), 
> type_max(T))
>       #define str2sh(...)    str2i(short, __VA_ARGS__)
>       --
>       get_gid(const char *restrict gidstr, gid_t *restrict gid)
>       {
>               return a2i(gid_t, gid, gidstr, NULL, 10, type_min(gid_t), 
> type_max(gid_t));
>       }
>       --
>       get_pid(const char *restrict pidstr, pid_t *restrict pid)
>       {
>               return a2i(pid_t, pid, pidstr, NULL, 10, 1, type_max(pid_t));
>       }
>       --
>       get_uid(const char *restrict uidstr, uid_t *restrict uid)
>       {
>               return a2i(uid_t, uid, uidstr, NULL, 10, type_min(uid_t), 
> type_max(uid_t));
>       }
>       --
>               } else {
>                       if (a2i(rlim_t, &l, value, NULL, 10, 0, 
> type_max(rlim_t)) == -1
>                           && errno != ENOTSUP)
>                       {
>       --
>       #define stype_max(T)                                                    
>       \
>       (                                                                       
>       \
>               (T) (((((T) 1 << (WIDTHOF(T) - 2)) - 1) << 1) + 1)              
>       \
>       )
>       #define utype_max(T)                                                    
>       \
>       (                                                                       
>       \
>               (T) -1                                                          
>       \
>       )
>       #define type_max(T)                                                     
>       \
>       (                                                                       
>       \
>               (T) (is_signed(T) ? stype_max(T) : utype_max(T))                
>       \
>       )
>       #define type_min(T)                                                     
>       \
>       (                                                                       
>       \
>               (T) ~type_max(T)                                                
>       \
>       )
>       --
>               const char       *pos;
>               struct id_range  result = {
>                       .first = type_max(id_t),
>                       .last = type_min(id_t)
>               };
>       --
>               static_assert(is_same_type(id_t, gid_t), "");
>               first = type_min(id_t);
>               last = type_max(id_t);
>               if (a2i(id_t, &first, str, &pos, 10, first, last) == -1
> 
> All of the uses are actually related to a2i() calls.  a2i() is
> a type-generic macro wrapper around strtoi(3bsd) --which itself is a
> wrapper around strtoimax(3)--, which works for arbitrary (non-boolean)
> integer types.
> 
> Another case where I would expect these macros to be useful is in the
> implementation of <stdbit.h> APIs.  Do we want to support things like
> popcount((bool)1)?  The answers are coupled, I think.
> 
> For example:
> 
>       T
>       bit_ceil(T x)
>       {
>               return 1 + (_Maxof(T) >> leading_zeros(x));
>       }

And I don't think we want to support bool in <stdbit.h>.  It doesn't
behave like all the other unsigned integer types:

        alx@devuan:~/tmp$ cat bc.c 
        #include <stdbool.h>
        #include <stdio.h>

        #define bit_ceil_b(x)   ((bool)1 + ((bool)1 >> (x == 0 ? 1 : 0)))
        #define bit_ceil_u1(x)  (1wbu    + (1wbu    >> (x == 0 ? 1 : 0)))

        int
        main(void)
        {
                bool b;
                unsigned _BitInt(1) u;

                b = 1;
                u = 1;

                printf("%d\n", (int) bit_ceil_b(b));
                printf("%d\n", (int) bit_ceil_u1(u));

                b = 0;
                u = 0;

                printf("%d\n", (int) bit_ceil_b(b));
                printf("%d\n", (int) bit_ceil_u1(u));
        }
        alx@devuan:~/tmp$ gcc -Wall -Wextra bc.c 
        alx@devuan:~/tmp$ ./a.out 
        2
        0
        1
        1

> > > Also, it's easy to extend features, but not so much to narrow them. 
> > > Thus, I find it better (safer) to exclude it, at least initially. I 
> > > welcome anyone interested in supporting bool to show a valid use case 
> > > for it.  I prefer to be cautious by default.
> > 
> > Exceptions are the enemy of good language design.  max/min on bool are 
> > well defined as are maxof/minof.  Excluding it from these operators seems 
> > fairly unnatural.  My 2 cents :-)
> 
> 
> Have a lovely day!
> Alex
> 
> -- 
> <https://www.alejandro-colomar.es>
> Use port 80 (that is, <...:80/>).



-- 
<https://www.alejandro-colomar.es>
Use port 80 (that is, <...:80/>).

Attachment: signature.asc
Description: PGP signature

Reply via email to