diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-12-21 13:36:58 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-12-21 13:36:58 -0500 |
| commit | e4d5bf73e4ad9dc51f923a32903011edfeae2908 (patch) | |
| tree | b0bd959d50bd7bf0c9751780288adb06a943787a /src/stdlib | |
| parent | f07c07e551b89b66b14936ae4573e656fbd7afb6 (diff) | |
Divide by zero checks
Diffstat (limited to 'src/stdlib')
| -rw-r--r-- | src/stdlib/bigint.c | 2 | ||||
| -rw-r--r-- | src/stdlib/bigint.h | 2 | ||||
| -rw-r--r-- | src/stdlib/reals.c | 34 |
3 files changed, 9 insertions, 29 deletions
diff --git a/src/stdlib/bigint.c b/src/stdlib/bigint.c index 2d145bd5..7b81e319 100644 --- a/src/stdlib/bigint.c +++ b/src/stdlib/bigint.c @@ -204,6 +204,7 @@ Int_t Int$slow_divided_by(Int_t dividend, Int_t divisor) { mpz_t quotient, remainder; mpz_init_set_int(quotient, dividend); mpz_init_set_int(remainder, divisor); + if unlikely (mpz_sgn(remainder) == 0) fail("Cannot divide by zero"); mpz_tdiv_qr(quotient, remainder, quotient, remainder); if (mpz_sgn(remainder) < 0) { bool d_positive = likely(divisor.small & 1L) ? divisor.small > 0x1L : mpz_sgn(divisor.big) > 0; @@ -219,6 +220,7 @@ Int_t Int$slow_modulo(Int_t x, Int_t modulus) { mpz_init_set_int(result, x); mpz_t divisor; mpz_init_set_int(divisor, modulus); + if unlikely (mpz_sgn(divisor) == 0) fail("Cannot divide by zero"); mpz_mod(result, result, divisor); return Int$from_mpz(result); } diff --git a/src/stdlib/bigint.h b/src/stdlib/bigint.h index 5bf33629..2936f2cd 100644 --- a/src/stdlib/bigint.h +++ b/src/stdlib/bigint.h @@ -103,6 +103,7 @@ MACROLIKE Int_t Int$divided_by(Int_t x, Int_t y) { // https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf const int64_t D = (x.small >> 2L); const int64_t d = (y.small >> 2L); + if unlikely (d == 0) fail("Cannot divide by zero"); int64_t q = D / d, r = D % d; q -= (r < 0L) * (2L * (d > 0L) - 1L); if likely (q == (int32_t)q) return (Int_t){.small = (q << 2L) | 1L}; @@ -116,6 +117,7 @@ MACROLIKE Int_t Int$modulo(Int_t x, Int_t y) { // https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf const int64_t D = (x.small >> 2L); const int64_t d = (y.small >> 2L); + if unlikely (d == 0) fail("Cannot divide by zero"); int64_t r = D % d; r -= (r < 0L) * (2L * (d < 0L) - 1L) * d; return (Int_t){.small = (r << 2L) | 1L}; diff --git a/src/stdlib/reals.c b/src/stdlib/reals.c index aee39414..56f247ff 100644 --- a/src/stdlib/reals.c +++ b/src/stdlib/reals.c @@ -16,7 +16,11 @@ struct ieee754_bits { uint64_t fraction : 53; }; -#define pow10(x, n) Int$times(x, Int$power(I(10), I(n))) +static inline Int_t pow10(Int_t x, int64_t n) { + if (n == 0) return x; + else if (n < 0) return Int$divided_by(x, Int$power(I(10), I(-n))); + else return Int$times(x, Int$power(I(10), I(n))); +} public Int_t Real$compute(Real_t r, int64_t decimals) { @@ -188,34 +192,6 @@ Real_t Real$times(Real_t x, Real_t y) { return result; } -// static Int_t Real$compute_inverse(Real_t r, int64_t decimals) { -// Real_t op = &r->userdata.children[0]; -// int64_t magnitude = approx_log10(op, 100); -// int64_t inv_magnitude = 1 - magnitude; -// int64_t digits_needed = inv_magnitude - decimals + 3; -// int64_t prec_needed = magnitude - digits_needed; -// int64_t log_scale_factor = -decimals - prec_needed; -// if (log_scale_factor < 0) return I(0); -// Int_t dividend = Int$left_shifted(I(1), I(log_scale_factor)); -// Int_t scaled_divisor = Real$compute(op, prec_needed); -// Int_t abs_scaled_divisor = Int$abs(scaled_divisor); -// Int_t adj_dividend = Int$plus(dividend, Int$right_shifted(abs_scaled_divisor, I(1))); -// // Adjustment so that final result is rounded. -// Int_t result = Int$divided_by(adj_dividend, abs_scaled_divisor); - -// if (Int$compare_value(scaled_divisor, I(0)) < 0) { -// return Int$negative(result); -// } else { -// return result; -// } - -// return r->approximation; -// } - -// public -// Real_t Real$inverse(Real_t x) { return new (struct Real_s, .compute = Real$compute_inverse, .userdata.children = x); -// } - static Int_t Real$compute_divided_by(Real_t r, int64_t decimals) { int64_t den_mag = approx_log10(&r->userdata.children[1], 100); Int_t num = Real$compute(&r->userdata.children[0], decimals * 2 - den_mag); |
