Is there an error somewhere, something that i missed? Is there an error somewhere, something that i missed?
Certainly have most of main street covered.
if (y == -1) return 0; is a nice trick.
y = abs(y); fails 32-bit math when int is 16-bit. Could use labs() or conditional code or an if() block. (Only real portability bug I see.)
Pedantic: int32_t is an optional type. It is missing and code fails to compile on select (dinosaur) machines that do not have 32-bit unpadded 2's complement.
Pedantic: On a select (unicorn) machine where int is 64-bit and int32_t exist, promotions occur. I do not see a problem though.
Pedantic: Usage of x ^ y obliges 2's complement encoding for correct functionality which is the case with intN_t here , but not all integers on all machines.
Adding a test harness would help.
Can it be simplified?
A shot at simplifying Euclidean division (result is always non-negative). Similar code may apply to the other 2 cases.
// Substitute `int` for `int32_t`, `long long`, etc.
int modulo_Euclidean(int x, int y) {
if (y == 0) exit(-1);
if (y == -1) return 0; // Prevent UB of INT_MIN % -1.
int m = x % y;
if (m < 0) {
// 2025 edit - a little micro optimization.
// m = (y < 0) ? m - y : m + y;
m -= (y < 0) ? y : -y;
// Don't do this. -INT_MIN is UB.
// m += (y < 0) ? -y : y;
}
return m;
}
Does not require intN_t math*, 2's complement, no padding, range constants, nor extended math.
It would be interesting to see if 64-bit math was really slower or a reasonable candidate.
int32_t mod_rem_or_euc(int32_t x, int32_t y) {
if (y == 0) exit(-1);
int_fast64_t m = (int_fast64_t) x % y;
...
}
* intN_t types are 2's complement, no padding.