diff --git a/include/cyclone/runtime.h b/include/cyclone/runtime.h index a71be75b..eb6ae077 100644 --- a/include/cyclone/runtime.h +++ b/include/cyclone/runtime.h @@ -526,6 +526,7 @@ object Cyc_num_cmp_va_list(void *data, int argc, va_list ns); void Cyc_expt(void *data, object cont, object x, object y); void Cyc_remainder(void *data, object cont, object num1, object num2); +void Cyc_get_ratio(void *data, object cont, object n, int numerator); object Cyc_number2string2(void *data, object cont, int argc, object n, ...); object Cyc_integer2char(void *data, object n); object Cyc_sum_op(void *data, common_type * x, object y); diff --git a/runtime.c b/runtime.c index d17b3749..b40dea56 100644 --- a/runtime.c +++ b/runtime.c @@ -8393,7 +8393,7 @@ void init_polyfills(void) // WIP - testing numerator/denominator computation // Code from https://stackoverflow.com/a/51142807/101258 // Return error flag -int split(double x, double *numerator, double *denominator) { +int num2ratio(double x, double *numerator, double *denominator) { if (!isfinite(x)) { *numerator = *denominator = 0.0; if (x > 0.0) *numerator = 1.0; @@ -8425,3 +8425,31 @@ int split(double x, double *numerator, double *denominator) { } return 0; } + +void Cyc_get_ratio(void *data, object cont, object n, int numerator) +{ + double d = 0.0; + Cyc_check_num(data, n); + + if (obj_is_int(n)) { + d = (double)obj_obj2int(n); + } else if (type_of(n) == double_tag) { + d = double_value(n); + } else if (type_of(n) == bignum_tag) { + d = mp_get_double(&bignum_value(n)); + } else { + Cyc_rt_raise2(data, "Unable to convert to ratio", n); + } + + { + double numer, denom; + make_double(val, 0.0); + num2ratio(d, &numer, &denom); + if (numerator) { + double_value(&val) = numer; + } else { + double_value(&val) = denom; + } + return_closcall1(data, cont, &val); + } +} diff --git a/scheme/base.sld b/scheme/base.sld index ee5b26f1..75bfe76a 100644 --- a/scheme/base.sld +++ b/scheme/base.sld @@ -196,6 +196,8 @@ string->utf8 denominator numerator + ;denominator2 + ;numerator2 parameterize read-bytevector read-bytevector! @@ -1488,6 +1490,13 @@ ;; Placeholders (define (denominator n) 1) (define (numerator n) n) + (define-c numerator2 + "(void *data, int argc, closure _, object k, object n)" + " Cyc_get_ratio(data, k, n, 1);") + + (define-c denominator2 + "(void *data, int argc, closure _, object k, object n)" + " Cyc_get_ratio(data, k, n, 0);") (define (quotient x y) (truncate (/ x y)))