aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-12-21 13:36:58 -0500
committerBruce Hill <bruce@bruce-hill.com>2025-12-21 13:36:58 -0500
commite4d5bf73e4ad9dc51f923a32903011edfeae2908 (patch)
treeb0bd959d50bd7bf0c9751780288adb06a943787a /src/stdlib
parentf07c07e551b89b66b14936ae4573e656fbd7afb6 (diff)
Divide by zero checks
Diffstat (limited to 'src/stdlib')
-rw-r--r--src/stdlib/bigint.c2
-rw-r--r--src/stdlib/bigint.h2
-rw-r--r--src/stdlib/reals.c34
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);