Skip to main content
added 201 characters in body
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97

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.

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;
  int m = x % y;
  if (m < 0) {
    m = (y < 0) ? m - y : m + 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.

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.

added 55 characters in body
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97

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 (dinosaurdinosaur) 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;
  int m = x % y;
  if (m < 0) {
    m = (y < 0) ? m - y : m + 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.

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;
  int m = x % y;
  if (m < 0) {
    m = (y < 0) ? m - y : m + 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.

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;
  int m = x % y;
  if (m < 0) {
    m = (y < 0) ? m - y : m + 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.

added 9 characters in body
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97

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 bithere , but not all integers on allall 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;
  int m = x % y;
  if (m < 0) {
    m = (y < 0) ? m - y : m + 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_fast64int_fast64_t) x % y;
  ...
}

* intN_t types are 2's complement, no padding.

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 bit 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;
  int m = x % y;
  if (m < 0) {
    m = (y < 0) ? m - y : m + 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) x % y;
  ...
}

* intN_t types are 2's complement, no padding.

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;
  int m = x % y;
  if (m < 0) {
    m = (y < 0) ? m - y : m + 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.

added 247 characters in body
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97
Loading
added 7 characters in body
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97
Loading
added 7 characters in body
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97
Loading
added 7 characters in body
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97
Loading
added 21 characters in body
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97
Loading
Source Link
chux
  • 36.5k
  • 2
  • 43
  • 97
Loading