https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118499
--- Comment #23 from Mikael Morin <mikael at gcc dot gnu.org> --- (In reply to Thomas Koenig from comment #20) > Right now, I am doing unsigned**unsigned. This is already a > bit larger than I originally thought. After this is committed, > we can still discuss how to extend it, I think. > > There is actually an interesting simplification for modulo > arithmetic, which I do not know how to do in C. > > Assume that power_simple() does the same as our current library > implementation. > > What I would like to do is > > uint8_t > power_complicated (uint8_t x, uint32_t n) > { > uint8_t zeros = __builtin_ctz (x); > uint8_t n_times_zeros; > > if (x == 0) > return 0; > > if (zeros == 0) > return power_simple (x, n & 127); > > n_times_zeros = n * zeros; > if (n_times_zeros > 8) > return 0; > > return power_simple (x, n & 255); > } > > (The n & 127 follows from Euler's theorem, because phi(2^n) = 2^(n-1)). > > So basically, a number with zeros trailing zeros to a power of x will > be zero under modulo 2^8 arithmetic if the number of zeros times n > is larger than 8. But I have not found a reasonable way to check if > n * zeros has overflowed. > I agree it's not easy in the general case. There is __builtin_mul_overflow that you can probably use (there are examples in the C testsuite). Or in this case, n can be bound beforehand to prevent overflow: if (n >= 8) return 0; n_times_zeros = n * zeros; if (n_times_zeros >= 8) return 0; Not very nice, but reasonable, isn't it?