/* Ypsilon Scheme System Copyright (c) 2004-2008 Y.FUJITA / LittleWing Company Limited. See license.txt for terms and conditions of use */ #include "core.h" #include "vm.h" #include "heap.h" #include "subr.h" #include "arith.h" #include "violation.h" // 9.9.4.1 Numerical type predicates // number? scm_obj_t subr_number_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { return number_pred(argv[0]) ? scm_true : scm_false; } wrong_number_of_arguments_violation(vm, "number?", 1, 1, argc, argv); return scm_undef; } // complex? scm_obj_t subr_complex_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { return number_pred(argv[0]) ? scm_true : scm_false; } wrong_number_of_arguments_violation(vm, "complex?", 1, 1, argc, argv); return scm_undef; } // real? scm_obj_t subr_real_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { return real_pred(argv[0]) ? scm_true : scm_false; } wrong_number_of_arguments_violation(vm, "real?", 1, 1, argc, argv); return scm_undef; } // rational? scm_obj_t subr_rational_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { return rational_pred(argv[0]) ? scm_true : scm_false; } wrong_number_of_arguments_violation(vm, "rational?", 1, 1, argc, argv); return scm_undef; } // integer? scm_obj_t subr_integer_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { return integer_pred(argv[0]) ? scm_true : scm_false; } wrong_number_of_arguments_violation(vm, "integer?", 1, 1, argc, argv); return scm_undef; } // real-valued? scm_obj_t subr_real_valued_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { return real_valued_pred(argv[0]) ? scm_true : scm_false; } wrong_number_of_arguments_violation(vm, "real-valued?", 1, 1, argc, argv); return scm_undef; } // rational-valued? scm_obj_t subr_rational_valued_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { return rational_valued_pred(argv[0]) ? scm_true : scm_false; } wrong_number_of_arguments_violation(vm, "rational-valued?", 1, 1, argc, argv); return scm_undef; } // integer-valued? scm_obj_t subr_integer_valued_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { return integer_valued_pred(argv[0]) ? scm_true : scm_false; } wrong_number_of_arguments_violation(vm, "integer-valued?", 1, 1, argc, argv); return scm_undef; } // exact? scm_obj_t subr_exact_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return n_exact_pred(argv[0]) ? scm_true : scm_false; wrong_type_argument_violation(vm, "exact?", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "exact?", 1, 1, argc, argv); return scm_undef; } // inexact? scm_obj_t subr_inexact_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return n_exact_pred(argv[0]) ? scm_false : scm_true; wrong_type_argument_violation(vm, "inexact?", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "inexact?", 1, 1, argc, argv); return scm_undef; } // 9.9.4.2 Generic conversions // inexact scm_obj_t subr_inexact(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return cnvt_to_inexact(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "inexact", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "inexact", 1, 1, argc, argv); return scm_undef; } // exact scm_obj_t subr_exact(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return cnvt_to_exact(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "exact", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "exact", 1, 1, argc, argv); return scm_undef; } // 9.9.4.3 Arithmetic operations // = scm_obj_t subr_num_eq(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (FIXNUMP(argv[0]) & FIXNUMP(argv[1])) return (argv[0] == argv[1]) ? scm_true : scm_false; if (BOTHFLONUMP(argv[0], argv[1])) return (FLONUM(argv[0]) == FLONUM(argv[1])) ? scm_true : scm_false; if (number_pred(argv[0])) { if (number_pred(argv[1])) return n_equal_pred(vm->m_heap, argv[0], argv[1]) ? scm_true : scm_false; wrong_type_argument_violation(vm, "=", 1, "number", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "=", 0, "number", argv[0], argc, argv); return scm_undef; } if (argc == 1) { if (number_pred(argv[0])) return scm_true; wrong_type_argument_violation(vm, "=", 0, "number", argv[0], argc, argv); return scm_undef; } if (argc >= 3) { for (int i = 0; i < argc; i++) { if (number_pred(argv[i])) continue; wrong_type_argument_violation(vm, "=", i, "number", argv[i], argc, argv); return scm_undef; } for (int i = 0; i < argc - 1; i++) { if (n_equal_pred(vm->m_heap, argv[i], argv[i + 1])) continue; return scm_false; } return scm_true; } wrong_number_of_arguments_violation(vm, "=", 1, -1, argc, argv); return scm_undef; } // < scm_obj_t subr_num_lt(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (FIXNUMP(argv[0]) & FIXNUMP(argv[1])) return (FIXNUM(argv[0]) < FIXNUM(argv[1])) ? scm_true : scm_false; if (BOTHFLONUMP(argv[0], argv[1])) return (FLONUM(argv[0]) < FLONUM(argv[1])) ? scm_true : scm_false; if (real_valued_pred(argv[0])) { if (real_valued_pred(argv[1])) { if (argv[0] == vm->m_heap->m_inherents[FL_NAN]) return scm_false; if (argv[1] == vm->m_heap->m_inherents[FL_NAN]) return scm_false; return (n_compare(vm->m_heap, argv[0], argv[1]) < 0) ? scm_true : scm_false; } wrong_type_argument_violation(vm, "<", 1, "real", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "<", 0, "real", argv[0], argc, argv); return scm_undef; } if (argc == 1) { if (real_valued_pred(argv[0])) { if (argv[0] == vm->m_heap->m_inherents[FL_NAN]) return scm_false; return scm_true; } wrong_type_argument_violation(vm, "<", 0, "real", argv[0], argc, argv); return scm_undef; } if (argc >= 3) { bool has_nan = false; for (int i = 0; i < argc; i++) { if (argv[i] == vm->m_heap->m_inherents[FL_NAN]) { has_nan = true; continue; } if (real_valued_pred(argv[i])) continue; wrong_type_argument_violation(vm, "<", i, "real", argv[i], argc, argv); return scm_undef; } if (has_nan) return scm_false; for (int i = 0; i < argc - 1; i++) { if (n_compare(vm->m_heap, argv[i], argv[i + 1]) < 0) continue; return scm_false; } return scm_true; } wrong_number_of_arguments_violation(vm, "<", 1, -1, argc, argv); return scm_undef; } // > scm_obj_t subr_num_gt(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (FIXNUMP(argv[0]) & FIXNUMP(argv[1])) return (FIXNUM(argv[0]) > FIXNUM(argv[1])) ? scm_true : scm_false; if (BOTHFLONUMP(argv[0], argv[1])) return (FLONUM(argv[0]) > FLONUM(argv[1])) ? scm_true : scm_false; if (real_valued_pred(argv[0])) { if (real_valued_pred(argv[1])) { if (argv[0] == vm->m_heap->m_inherents[FL_NAN]) return scm_false; if (argv[1] == vm->m_heap->m_inherents[FL_NAN]) return scm_false; return (n_compare(vm->m_heap, argv[0], argv[1]) > 0) ? scm_true : scm_false; } wrong_type_argument_violation(vm, ">", 1, "real", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, ">", 0, "real", argv[0], argc, argv); return scm_undef; } if (argc == 1) { if (real_valued_pred(argv[0])) { if (argv[0] == vm->m_heap->m_inherents[FL_NAN]) return scm_false; return scm_true; } wrong_type_argument_violation(vm, ">", 0, "real", argv[0], argc, argv); return scm_undef; } if (argc >= 3) { bool has_nan = false; for (int i = 0; i < argc; i++) { if (argv[i] == vm->m_heap->m_inherents[FL_NAN]) { has_nan = true; continue; } if (real_valued_pred(argv[i])) continue; wrong_type_argument_violation(vm, ">", i, "real", argv[i], argc, argv); return scm_undef; } if (has_nan) return scm_false; for (int i = 0; i < argc - 1; i++) { if (n_compare(vm->m_heap, argv[i], argv[i + 1]) > 0) continue; return scm_false; } return scm_true; } wrong_number_of_arguments_violation(vm, ">", 1, -1, argc, argv); return scm_undef; } // <= scm_obj_t subr_num_le(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (FIXNUMP(argv[0]) & FIXNUMP(argv[1])) return (FIXNUM(argv[0]) <= FIXNUM(argv[1])) ? scm_true : scm_false; if (BOTHFLONUMP(argv[0], argv[1])) return (FLONUM(argv[0]) <= FLONUM(argv[1])) ? scm_true : scm_false; if (real_valued_pred(argv[0])) { if (real_valued_pred(argv[1])) { if (argv[0] == vm->m_heap->m_inherents[FL_NAN]) return scm_false; if (argv[1] == vm->m_heap->m_inherents[FL_NAN]) return scm_false; return (n_compare(vm->m_heap, argv[0], argv[1]) <= 0) ? scm_true : scm_false; } wrong_type_argument_violation(vm, "<=", 1, "real", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "<=", 0, "real", argv[0], argc, argv); return scm_undef; } if (argc == 1) { if (real_valued_pred(argv[0])) { if (argv[0] == vm->m_heap->m_inherents[FL_NAN]) return scm_false; return scm_true; } wrong_type_argument_violation(vm, "<=", 0, "real", argv[0], argc, argv); return scm_undef; } if (argc >= 3) { bool has_nan = false; for (int i = 0; i < argc; i++) { if (argv[i] == vm->m_heap->m_inherents[FL_NAN]) { has_nan = true; continue; } if (real_valued_pred(argv[i])) continue; wrong_type_argument_violation(vm, "<=", i, "real", argv[i], argc, argv); return scm_undef; } if (has_nan) return scm_false; for (int i = 0; i < argc - 1; i++) { if (n_compare(vm->m_heap, argv[i], argv[i + 1]) <= 0) continue; return scm_false; } return scm_true; } wrong_number_of_arguments_violation(vm, "<=", 1, -1, argc, argv); return scm_undef; } // >= scm_obj_t subr_num_ge(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (FIXNUMP(argv[0]) & FIXNUMP(argv[1])) return (FIXNUM(argv[0]) >= FIXNUM(argv[1])) ? scm_true : scm_false; if (BOTHFLONUMP(argv[0], argv[1])) return (FLONUM(argv[0]) >= FLONUM(argv[1])) ? scm_true : scm_false; if (real_valued_pred(argv[0])) { if (real_valued_pred(argv[1])) { if (argv[0] == vm->m_heap->m_inherents[FL_NAN]) return scm_false; if (argv[1] == vm->m_heap->m_inherents[FL_NAN]) return scm_false; return (n_compare(vm->m_heap, argv[0], argv[1]) >= 0) ? scm_true : scm_false; } wrong_type_argument_violation(vm, ">=", 1, "real", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, ">=", 0, "real", argv[0], argc, argv); return scm_undef; } if (argc == 1) { if (real_valued_pred(argv[0])) { if (argv[0] == vm->m_heap->m_inherents[FL_NAN]) return scm_false; return scm_true; } wrong_type_argument_violation(vm, ">=", 0, "real", argv[0], argc, argv); return scm_undef; } if (argc >= 3) { bool has_nan = false; for (int i = 0; i < argc; i++) { if (argv[i] == vm->m_heap->m_inherents[FL_NAN]) { has_nan = true; continue; } if (real_valued_pred(argv[i])) continue; wrong_type_argument_violation(vm, ">=", i, "real", argv[i], argc, argv); return scm_undef; } if (has_nan) return scm_false; for (int i = 0; i < argc - 1; i++) { if (n_compare(vm->m_heap, argv[i], argv[i + 1]) >= 0) continue; return scm_false; } return scm_true; } wrong_number_of_arguments_violation(vm, ">=", 1, -1, argc, argv); return scm_undef; } // zero? scm_obj_t subr_zero_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return n_zero_pred(argv[0]) ? scm_true : scm_false; wrong_type_argument_violation(vm, "zero?", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "zero?", 1, 1, argc, argv); return scm_undef; } // positive? scm_obj_t subr_positive_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (real_valued_pred(argv[0])) return n_positive_pred(argv[0]) ? scm_true : scm_false; wrong_type_argument_violation(vm, "positive?", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "positive?", 1, 1, argc, argv); return scm_undef; } // negative? scm_obj_t subr_negative_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (real_valued_pred(argv[0])) return n_negative_pred(argv[0]) ? scm_true : scm_false; wrong_type_argument_violation(vm, "negative?", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "negative?", 1, 1, argc, argv); return scm_undef; } // odd? scm_obj_t subr_odd_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (integer_valued_pred(argv[0])) { return n_even_pred(argv[0]) ? scm_false : scm_true; } wrong_type_argument_violation(vm, "odd?", 0, "integer", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "odd?", 1, 1, argc, argv); return scm_undef; } // even? scm_obj_t subr_even_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (integer_valued_pred(argv[0])) { return n_even_pred(argv[0]) ? scm_true : scm_false; } wrong_type_argument_violation(vm, "even?", 0, "integer", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "even?", 1, 1, argc, argv); return scm_undef; } // finite? scm_obj_t subr_finite_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (real_pred(argv[0])) { if (FLONUMP(argv[0])) { scm_flonum_t flonum = (scm_flonum_t)argv[0]; if (isnan(flonum->value)) return scm_false; if (isinf(flonum->value)) return scm_false; } return scm_true; } wrong_type_argument_violation(vm, "finite?", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "finite?", 1, 1, argc, argv); return scm_undef; } // infinite? scm_obj_t subr_infinite_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (real_pred(argv[0])) { if (FLONUMP(argv[0])) { scm_flonum_t flonum = (scm_flonum_t)argv[0]; if (isinf(flonum->value)) return scm_true; } return scm_false; } wrong_type_argument_violation(vm, "infinite?", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "infinite?", 1, 1, argc, argv); return scm_undef; } // nan? scm_obj_t subr_nan_pred(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (real_pred(argv[0])) { if (FLONUMP(argv[0])) { scm_flonum_t flonum = (scm_flonum_t)argv[0]; if (isnan(flonum->value)) return scm_true; } return scm_false; } wrong_type_argument_violation(vm, "nan?", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "nan?", 1, 1, argc, argv); return scm_undef; } // max min (r6rs-aux.scm) // + scm_obj_t subr_num_add(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (FIXNUMP(argv[0]) & FIXNUMP(argv[1])) return intptr_to_integer(vm->m_heap, FIXNUM(argv[0]) + FIXNUM(argv[1])); if (BOTHFLONUMP(argv[0], argv[1])) return make_flonum(vm->m_heap, FLONUM(argv[0]) + FLONUM(argv[1])); if (number_pred(argv[0])) { if (number_pred(argv[1])) return arith_add(vm->m_heap, argv[0], argv[1]); wrong_type_argument_violation(vm, "+", 1, "number", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "+", 0, "number", argv[0], argc, argv); return scm_undef; } if (argc == 1) { if (number_pred(argv[0])) return argv[0]; wrong_type_argument_violation(vm, "+", 0, "number", argv[0], argc, argv); return scm_undef; } if (argc == 0) return MAKEFIXNUM(0); for (int i = 0; i < argc; i++) { if (number_pred(argv[i])) continue; wrong_type_argument_violation(vm, "+", i, "number", argv[i], argc, argv); return scm_undef; } scm_obj_t acc = argv[0]; for (int i = 1; i < argc; i++) { acc = arith_add(vm->m_heap, acc, argv[i]); } return acc; } // - scm_obj_t subr_num_sub(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (FIXNUMP(argv[0]) & FIXNUMP(argv[1])) return intptr_to_integer(vm->m_heap, FIXNUM(argv[0]) - FIXNUM(argv[1])); if (BOTHFLONUMP(argv[0], argv[1])) return make_flonum(vm->m_heap, FLONUM(argv[0]) - FLONUM(argv[1])); if (number_pred(argv[0])) { if (number_pred(argv[1])) return arith_sub(vm->m_heap, argv[0], argv[1]); wrong_type_argument_violation(vm, "-", 1, "number", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "-", 0, "number", argv[0], argc, argv); return scm_undef; } if (argc == 1) { if (number_pred(argv[0])) return arith_negate(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "-", 0, "number", argv[0], argc, argv); return scm_undef; } if (argc == 0) { wrong_number_of_arguments_violation(vm, "-", 1, -1, argc, argv); return scm_undef; } for (int i = 0; i < argc; i++) { if (number_pred(argv[i])) continue; wrong_type_argument_violation(vm, "-", i, "number", argv[i], argc, argv); return scm_undef; } scm_obj_t acc = argv[0]; for (int i = 1; i < argc; i++) { acc = arith_sub(vm->m_heap, acc, argv[i]); } return acc; } // * scm_obj_t subr_num_mul(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (FIXNUMP(argv[0]) & FIXNUMP(argv[1])) { #if ARCH_LP64 int128_t n128 = (int128_t)FIXNUM(argv[0]) * FIXNUM(argv[1]); if ((n128 >= FIXNUM_MIN) & (n128 <= FIXNUM_MAX)) return MAKEFIXNUM((intptr_t)n128); return int128_to_bignum(vm->m_heap, n128); #else int64_t n64 = (int64_t)FIXNUM(argv[0]) * FIXNUM(argv[1]); if ((n64 >= FIXNUM_MIN) & (n64 <= FIXNUM_MAX)) return MAKEFIXNUM((intptr_t)n64); return int64_to_bignum(vm->m_heap, n64); #endif } if (BOTHFLONUMP(argv[0], argv[1])) return make_flonum(vm->m_heap, FLONUM(argv[0]) * FLONUM(argv[1])); if (number_pred(argv[0])) { if (number_pred(argv[1])) return arith_mul(vm->m_heap, argv[0], argv[1]); wrong_type_argument_violation(vm, "*", 1, "number", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "*", 0, "number", argv[0], argc, argv); return scm_undef; } if (argc > 2) { for (int i = 0; i < argc; i++) { if (number_pred(argv[i])) continue; wrong_type_argument_violation(vm, "*", i, "number", argv[i], argc, argv); return scm_undef; } scm_obj_t acc = argv[0]; for (int i = 1; i < argc; i++) { acc = arith_mul(vm->m_heap, acc, argv[i]); } return acc; } if (argc == 1) { if (number_pred(argv[0])) return argv[0]; wrong_type_argument_violation(vm, "*", 0, "number", argv[0], argc, argv); return scm_undef; } return MAKEFIXNUM(1); } // / scm_obj_t subr_num_div(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (BOTHFLONUMP(argv[0], argv[1])) return make_flonum(vm->m_heap, FLONUM(argv[0]) / FLONUM(argv[1])); if (argv[1] == MAKEFIXNUM(0)) { if (number_pred(argv[0])) { if (n_exact_pred(argv[0])) { invalid_argument_violation(vm, "/", "undefined for 0", NULL, 0, argc, argv); return scm_undef; } return arith_div(vm->m_heap, argv[0], make_flonum(vm->m_heap, 0.0)); } } if (number_pred(argv[0])) { if (number_pred(argv[1])) return arith_div(vm->m_heap, argv[0], argv[1]); wrong_type_argument_violation(vm, "/", 1, "number", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "/", 0, "number", argv[0], argc, argv); return scm_undef; } if (argc == 1) { if (number_pred(argv[0])) { if (argv[0] != MAKEFIXNUM(0)) return arith_inverse(vm->m_heap, argv[0]); invalid_argument_violation(vm, "/", "undefined for 0", NULL, 0, argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "/", 0, "number", argv[0], argc, argv); return scm_undef; } if (argc == 0) { wrong_number_of_arguments_violation(vm, "/", 1, -1, argc, argv); return scm_undef; } for (int i = 0; i < argc; i++) { if (number_pred(argv[i])) continue; wrong_type_argument_violation(vm, "/", i, "number", argv[i], argc, argv); return scm_undef; } scm_obj_t acc = argv[0]; for (int i = 1; i < argc; i++) { if (argv[i] == MAKEFIXNUM(0)) { if (n_exact_pred(acc)) { invalid_argument_violation(vm, "/", "undefined for 0", NULL, i, argc, argv); return scm_undef; } acc = arith_div(vm->m_heap, acc, make_flonum(vm->m_heap, 0.0)); continue; } acc = arith_div(vm->m_heap, acc, argv[i]); } return acc; } // abs scm_obj_t subr_abs(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (real_pred(argv[0])) return arith_magnitude(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "abs", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "abs", 1, 1, argc, argv); return scm_undef; } // div-and-mod -> r6rs-aux.scm // div scm_obj_t subr_int_div(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (real_pred(argv[0])) { if (n_finite_pred(argv[0])) { if (real_pred(argv[1])) { if (!n_zero_pred(argv[1])) { return arith_integer_div(vm->m_heap, argv[0], argv[1]); } invalid_argument_violation(vm, "div", "undefined for 0", NULL, 0, argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "div", 0, "real", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "div", 0, "neither infinite nor a NaN", argv[0], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "div", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "div", 2, 2, argc, argv); return scm_undef; } // mod div0-and-mod0 -> r6rs-aux.scm // div0 scm_obj_t subr_int_div0(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (real_pred(argv[0])) { if (n_finite_pred(argv[0])) { if (real_pred(argv[1])) { if (!n_zero_pred(argv[1])) { return arith_integer_div0(vm->m_heap, argv[0], argv[1]); } invalid_argument_violation(vm, "div0", "undefined for 0", NULL, 0, argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "div0", 0, "real", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "div0", 0, "neither infinite nor a NaN", argv[0], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "div0", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "div0", 2, 2, argc, argv); return scm_undef; } // mod0 gcm lcm -> r6rs-aux.scm // numerator scm_obj_t subr_numerator(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (real_valued_pred(argv[0])) { if (FLONUMP(argv[0]) && FLONUM(argv[0]) == 0.0) return argv[0]; bool inexact = FLONUMP(argv[0]); scm_obj_t obj = cnvt_to_exact(vm->m_heap, argv[0]); if (RATIONALP(obj)) { if (inexact) return cnvt_to_inexact(vm->m_heap, ((scm_rational_t)obj)->nume); return ((scm_rational_t)obj)->nume; } return inexact ? cnvt_to_inexact(vm->m_heap, obj) : obj; } wrong_type_argument_violation(vm, "numerator", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "numerator", 1, 1, argc, argv); return scm_undef; } // denominator scm_obj_t subr_denominator(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (real_valued_pred(argv[0])) { bool inexact = FLONUMP(argv[0]); scm_obj_t obj = cnvt_to_exact(vm->m_heap, argv[0]); if (RATIONALP(obj)) { if (inexact) return cnvt_to_inexact(vm->m_heap, ((scm_rational_t)obj)->deno); return ((scm_rational_t)obj)->deno; } return inexact ? make_flonum(vm->m_heap, 1.0) : MAKEFIXNUM(1); } wrong_type_argument_violation(vm, "denominator", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "denominator", 1, 1, argc, argv); return scm_undef; } // floor scm_obj_t subr_floor(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (COMPLEXP(argv[0])) { scm_complex_t cn = (scm_complex_t)argv[0]; if (n_zero_pred(cn->imag)) { argv[0] = cn->real; /*** FALL THROUGH ***/ } else { wrong_type_argument_violation(vm, "floor", 0, "real", argv[0], argc, argv); return scm_undef; } } if (FLONUMP(argv[0])) { double value = ((scm_flonum_t)argv[0])->value; return make_flonum(vm->m_heap, floor(value)); } if (FIXNUMP(argv[0]) || BIGNUMP(argv[0])) return argv[0]; if (RATIONALP(argv[0])) return arith_floor(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "floor", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "floor", 1, 1, argc, argv); return scm_undef; } // ceiling scm_obj_t subr_ceiling(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (COMPLEXP(argv[0])) { scm_complex_t cn = (scm_complex_t)argv[0]; if (n_zero_pred(cn->imag)) { argv[0] = cn->real; /*** FALL THROUGH ***/ } else { wrong_type_argument_violation(vm, "ceiling", 0, "real", argv[0], argc, argv); return scm_undef; } } if (FLONUMP(argv[0])) { double value = ((scm_flonum_t)argv[0])->value; return make_flonum(vm->m_heap, ceil(value)); } if (FIXNUMP(argv[0])) return argv[0]; if (BIGNUMP(argv[0])) return argv[0]; if (RATIONALP(argv[0])) { scm_rational_t rn = (scm_rational_t)argv[0]; if (!n_negative_pred(rn->nume)) { return arith_add(vm->m_heap, arith_quotient(vm->m_heap, rn->nume, rn->deno), MAKEFIXNUM(1)); } return arith_quotient(vm->m_heap, rn->nume, rn->deno); } wrong_type_argument_violation(vm, "ceiling", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "ceiling", 1, 1, argc, argv); return scm_undef; } // truncate scm_obj_t subr_truncate(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (COMPLEXP(argv[0])) { scm_complex_t cn = (scm_complex_t)argv[0]; if (n_zero_pred(cn->imag)) { argv[0] = cn->real; /*** FALL THROUGH ***/ } else { wrong_type_argument_violation(vm, "truncate", 0, "real", argv[0], argc, argv); return scm_undef; } } if (FLONUMP(argv[0])) { double value = ((scm_flonum_t)argv[0])->value; return make_flonum(vm->m_heap, trunc(value)); } if (FIXNUMP(argv[0])) return argv[0]; if (BIGNUMP(argv[0])) return argv[0]; if (RATIONALP(argv[0])) { scm_rational_t rn = (scm_rational_t)argv[0]; return arith_quotient(vm->m_heap, rn->nume, rn->deno); } wrong_type_argument_violation(vm, "truncate", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "truncate", 1, 1, argc, argv); return scm_undef; } // round scm_obj_t subr_round(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (COMPLEXP(argv[0])) { scm_complex_t cn = (scm_complex_t)argv[0]; if (n_zero_pred(cn->imag)) { argv[0] = cn->real; /*** FALL THROUGH ***/ } else { wrong_type_argument_violation(vm, "round", 0, "real", argv[0], argc, argv); return scm_undef; } } if (FLONUMP(argv[0])) { double value = ((scm_flonum_t)argv[0])->value; double ans = floor(value + 0.5); if (ans != value + 0.5) return make_flonum(vm->m_heap, ans); if (ans * 0.5 == floor(ans * 0.5)) return make_flonum(vm->m_heap, ans); return make_flonum(vm->m_heap, ans - 1.0); } if (FIXNUMP(argv[0])) return argv[0]; if (BIGNUMP(argv[0])) return argv[0]; if (RATIONALP(argv[0])) { scm_rational_t rn = (scm_rational_t)argv[0]; bool negative = n_negative_pred(rn->nume); scm_rational_rec_t half; half.hdr = scm_hdr_rational; half.nume = negative ? MAKEFIXNUM(-1) : MAKEFIXNUM(1); half.deno = MAKEFIXNUM(2); scm_obj_t n_and_half = arith_add(vm->m_heap, rn, &half); if (RATIONALP(n_and_half)) { return arith_quotient(vm->m_heap, ((scm_rational_t)n_and_half)->nume, ((scm_rational_t)n_and_half)->deno); } else { if (n_even_pred(n_and_half)) return n_and_half; return arith_add(vm->m_heap, n_and_half, negative ? MAKEFIXNUM(1) : MAKEFIXNUM(-1)); } } wrong_type_argument_violation(vm, "round", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "round", 1, 1, argc, argv); return scm_undef; } // rationalize -> r6rs-aux.scm // exp scm_obj_t subr_exp(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return arith_exp(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "exp", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "exp", 1, 1, argc, argv); return scm_undef; } // log scm_obj_t subr_log(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) { if (argv[0] == MAKEFIXNUM(0)) { invalid_argument_violation(vm, "log", "undefined for 0", NULL, 0, argc, argv); return scm_undef; } return arith_log(vm->m_heap, argv[0]); } wrong_type_argument_violation(vm, "log", 0, "number", argv[0], argc, argv); return scm_undef; } if (argc == 2) { if (number_pred(argv[0])) { if (argv[0] == MAKEFIXNUM(0)) { invalid_argument_violation(vm, "log", "undefined for 0", NULL, 0, argc, argv); return scm_undef; } if (number_pred(argv[1])) { if (argv[1] == MAKEFIXNUM(0)) { invalid_argument_violation(vm, "log", "undefined for base 0", NULL, 0, argc, argv); return scm_undef; } return arith_div(vm->m_heap, arith_log(vm->m_heap, argv[0]), arith_log(vm->m_heap, argv[1])); } wrong_type_argument_violation(vm, "log", 1, "number", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "log", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "log", 1, 1, argc, argv); return scm_undef; } // sin scm_obj_t subr_sin(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return arith_sin(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "sin", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "sin", 1, 1, argc, argv); return scm_undef; } // cos scm_obj_t subr_cos(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return arith_cos(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "cos", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "cos", 1, 1, argc, argv); return scm_undef; } // tan scm_obj_t subr_tan(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return arith_tan(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "tan", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "tan", 1, 1, argc, argv); return scm_undef; } // asin scm_obj_t subr_asin(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return arith_asin(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "asin", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "asin", 1, 1, argc, argv); return scm_undef; } // acos scm_obj_t subr_acos(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return arith_acos(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "acos", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "acos", 1, 1, argc, argv); return scm_undef; } // atan scm_obj_t subr_atan(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return arith_atan(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "atan", 0, "number", argv[0], argc, argv); return scm_undef; } if (argc == 2) { if (real_valued_pred(argv[0])) { if (real_valued_pred(argv[1])) { return arith_atan2(vm->m_heap, argv[0], argv[1]); } wrong_type_argument_violation(vm, "atan", 1, "real", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "atan", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "atan", 1, 2, argc, argv); return scm_undef; } // sqrt scm_obj_t subr_sqrt(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return arith_sqrt(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "sqrt", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "sqrt", 1, 1, argc, argv); return scm_undef; } // exact-integer-sqrt scm_obj_t subr_exact_integer_sqrt(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (exact_non_negative_integer_pred(argv[0])) { exact_integer_sqrt_ans_t ans = arith_exact_integer_sqrt(vm->m_heap, argv[0]); scm_values_t obj = make_values(vm->m_heap, 2); obj->elts[0] = ans.s; obj->elts[1] = ans.r; return obj; } wrong_type_argument_violation(vm, "exact-integer-sqrt", 0, "non-negative exact integer", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "exact-integer-sqrt", 1, 1, argc, argv); return scm_undef; } // expt scm_obj_t subr_expt(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (number_pred(argv[0])) { if (number_pred(argv[1])) { if (argv[0] == MAKEFIXNUM(1)) { if (n_exact_pred(argv[1])) return MAKEFIXNUM(1); return make_flonum(vm->m_heap, 1.0); } if (argv[0] == MAKEFIXNUM(-1) && n_exact_pred(argv[1])) { if (n_even_pred(argv[1])) return MAKEFIXNUM(1); return MAKEFIXNUM(-1); } if (argv[0] == MAKEFIXNUM(0)) { if (n_zero_pred(argv[1])) { if (n_exact_pred(argv[1])) return MAKEFIXNUM(1); return make_flonum(vm->m_heap, 1.0); } if (real_valued_pred(argv[1])) { if (n_negative_pred(argv[1])) return make_complex(vm->m_heap, VALUE_NAN, VALUE_NAN); if (n_exact_pred(argv[1])) return MAKEFIXNUM(0); return make_flonum(vm->m_heap, 0.0); } else { assert(COMPLEXP(argv[1])); if (n_positive_pred(((scm_complex_t)argv[1])->real)) { if (n_exact_pred(argv[1])) return MAKEFIXNUM(0); return make_flonum(vm->m_heap, 0.0); } return make_complex(vm->m_heap, VALUE_NAN, VALUE_NAN); } } if (n_exact_pred(argv[0]) && BIGNUMP(argv[1])) { invalid_argument_violation(vm, "expt", "calculated number is too big to fit into memory", NULL, 0, argc, argv); return scm_undef; } return arith_expt(vm->m_heap, argv[0], argv[1]); } wrong_type_argument_violation(vm, "expt", 1, "number", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "expt", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "expt", 2, 2, argc, argv); return scm_undef; } // make-rectangular scm_obj_t subr_make_rectangular(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (real_valued_pred(argv[0])) { if (real_valued_pred(argv[1])) { scm_obj_t real = COMPLEXP(argv[0]) ? ((scm_complex_t)argv[0])->real : argv[0]; scm_obj_t imag = COMPLEXP(argv[1]) ? ((scm_complex_t)argv[1])->real : argv[1]; return arith_rectangular(vm->m_heap, real, imag); } wrong_type_argument_violation(vm, "make-rectangular", 1, "real", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "make-rectangular", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "make-rectangular", 2, 2, argc, argv); return scm_undef; } // make-polar scm_obj_t subr_make_polar(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 2) { if (real_valued_pred(argv[0])) { if (real_valued_pred(argv[1])) { scm_obj_t real = COMPLEXP(argv[0]) ? ((scm_complex_t)argv[0])->real : argv[0]; scm_obj_t imag = COMPLEXP(argv[1]) ? ((scm_complex_t)argv[1])->real : argv[1]; return arith_polar(vm->m_heap, real, imag); } wrong_type_argument_violation(vm, "make-polar", 1, "real", argv[1], argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "make-polar", 0, "real", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "make-polar", 2, 2, argc, argv); return scm_undef; } // real-part scm_obj_t subr_real_part(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (COMPLEXP(argv[0])) return ((scm_complex_t)argv[0])->real; if (real_valued_pred(argv[0])) return argv[0]; wrong_type_argument_violation(vm, "real-part", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "real-part", 1, 1, argc, argv); return scm_undef; } // imag-part scm_obj_t subr_imag_part(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (COMPLEXP(argv[0])) return ((scm_complex_t)argv[0])->imag; if (FIXNUMP(argv[0]) || FLONUMP(argv[0]) || BIGNUMP(argv[0]) || RATIONALP(argv[0])) return MAKEFIXNUM(0); wrong_type_argument_violation(vm, "imag-part", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "imag-part", 1, 1, argc, argv); return scm_undef; } // magnitude scm_obj_t subr_magnitude(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return arith_magnitude(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "magnitude", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "magnitude", 1, 1, argc, argv); return scm_undef; } // angle scm_obj_t subr_angle(VM* vm, int argc, scm_obj_t argv[]) { if (argc == 1) { if (number_pred(argv[0])) return arith_angle(vm->m_heap, argv[0]); wrong_type_argument_violation(vm, "angle", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "angle", 1, 1, argc, argv); return scm_undef; } // 9.9.4.4 Numarical Input and Output // number->string scm_obj_t subr_number_to_string(VM* vm, int argc, scm_obj_t argv[]) { if ((argc == 1) || (argc == 2) || (argc == 3)) { int radix = 10; if (argc >= 2) { if (FIXNUMP(argv[1])) { radix = FIXNUM(argv[1]); switch (radix) { case 2: case 8: case 10: case 16: break; default: invalid_argument_violation(vm, "number->string", "radix must be either 2, 8, 10 or 16, but got", argv[1], 1, argc, argv); return scm_undef; } } else { if (exact_non_negative_integer_pred(argv[1])) { invalid_argument_violation(vm, "number->string", "radix must be either 2, 8, 10 or 16, but got", argv[1], 1, argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "number->string", 1, "exact non-negative integer", argv[1], argc, argv); return scm_undef; } if (argc == 3) { if (exact_non_negative_integer_pred(argv[2])) { // precision ignored } else { wrong_type_argument_violation(vm, "number->string", 2, "exact non-negative integer", argv[2], argc, argv); return scm_undef; } } } if (number_pred(argv[0])) { if (radix == 10 || n_exact_pred(argv[0])) return cnvt_number_to_string(vm->m_heap, argv[0], radix); invalid_argument_violation(vm, "number->string", "radix must be 10 for inexact, but got", argv[1], 1, argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "number->string", 0, "number", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "number->string", 1, 3, argc, argv); return scm_undef; } // string->number scm_obj_t subr_string_to_number(VM* vm, int argc, scm_obj_t argv[]) { if ((argc == 1) || (argc == 2)) { int radix = 0; if (argc == 2) { if (FIXNUMP(argv[1])) { radix = FIXNUM(argv[1]); switch (radix) { case 2: case 8: case 10: case 16: break; default: invalid_argument_violation(vm, "string->number", "radix must be either 2, 8, 10 or 16, but got", argv[1], 1, argc, argv); return scm_undef; } } else { if (exact_non_negative_integer_pred(argv[1])) { invalid_argument_violation(vm, "string->number", "radix must be either 2, 8, 10 or 16, but got", argv[1], 1, argc, argv); return scm_undef; } wrong_type_argument_violation(vm, "string->number", 1, "exact non-negative integer", argv[1], argc, argv); return scm_undef; } } if (STRINGP(argv[0])) { scm_string_t string = (scm_string_t)argv[0]; return parse_number(vm->m_heap, string->name, 0, radix); } wrong_type_argument_violation(vm, "string->number", 0, "string", argv[0], argc, argv); return scm_undef; } wrong_number_of_arguments_violation(vm, "string->number", 1, 2, argc, argv); return scm_undef; } /// void init_subr_base_arith(object_heap_t* heap) { #define DEFSUBR(SYM, FUNC) heap->intern_system_subr(SYM, FUNC) DEFSUBR("number?", subr_number_pred); DEFSUBR("complex?", subr_complex_pred); DEFSUBR("real?", subr_real_pred); DEFSUBR("rational?", subr_rational_pred); DEFSUBR("integer?", subr_integer_pred); DEFSUBR("real-valued?", subr_real_valued_pred); DEFSUBR("rational-valued?", subr_rational_valued_pred); DEFSUBR("integer-valued?", subr_integer_valued_pred); DEFSUBR("exact?", subr_exact_pred); DEFSUBR("inexact?", subr_inexact_pred); DEFSUBR("inexact", subr_inexact); DEFSUBR("exact", subr_exact); DEFSUBR("=", subr_num_eq); DEFSUBR("<", subr_num_lt); DEFSUBR(">", subr_num_gt); DEFSUBR("<=", subr_num_le); DEFSUBR(">=", subr_num_ge); DEFSUBR("zero?", subr_zero_pred); DEFSUBR("positive?", subr_positive_pred); DEFSUBR("negative?", subr_negative_pred); DEFSUBR("odd?", subr_odd_pred); DEFSUBR("even?", subr_even_pred); DEFSUBR("finite?", subr_finite_pred); DEFSUBR("infinite?", subr_infinite_pred); DEFSUBR("nan?", subr_nan_pred); DEFSUBR("+", subr_num_add); DEFSUBR("-", subr_num_sub); DEFSUBR("*", subr_num_mul); DEFSUBR("/", subr_num_div); DEFSUBR("div", subr_int_div); DEFSUBR("div0", subr_int_div0); DEFSUBR("abs", subr_abs); DEFSUBR("numerator", subr_numerator); DEFSUBR("denominator", subr_denominator); DEFSUBR("floor", subr_floor); DEFSUBR("ceiling", subr_ceiling); DEFSUBR("truncate", subr_truncate); DEFSUBR("round", subr_round); DEFSUBR("exp", subr_exp); DEFSUBR("log", subr_log); DEFSUBR("sin", subr_sin); DEFSUBR("cos", subr_cos); DEFSUBR("tan", subr_tan); DEFSUBR("asin", subr_asin); DEFSUBR("acos", subr_acos); DEFSUBR("atan", subr_atan); DEFSUBR("sqrt", subr_sqrt); DEFSUBR("exact-integer-sqrt", subr_exact_integer_sqrt); DEFSUBR("expt", subr_expt); DEFSUBR("make-rectangular", subr_make_rectangular); DEFSUBR("make-polar", subr_make_polar); DEFSUBR("real-part", subr_real_part); DEFSUBR("imag-part", subr_imag_part); DEFSUBR("magnitude", subr_magnitude); DEFSUBR("angle", subr_angle); DEFSUBR("number->string", subr_number_to_string); DEFSUBR("string->number", subr_string_to_number); }