/* Extension that defines fmod, modulo on floating-point numbers. The extension is equivalent to Scheme source of them form: (define (fmod a b) ...) */ #include "escheme.h" #include /**************************************************/ /* Every C implementation of a Scheme function takes argc and an array of Scheme_Object* values for argv, and returns a Scheme_Object*: */ static Scheme_Object *sch_fmod(int argc, Scheme_Object **argv) { /* Because we'll use scheme_make_prim_w_arity, MzScheme will have already checked that we're getting the right number of arguments. */ Scheme_Object *a = argv[0], *b = argv[1]; double v; /* Make sure we got real numbers, and complain if not: */ if (!SCHEME_REALP(a)) scheme_wrong_type("fmod", "real number", 0, argc, argv); /* 1st arg wrong ----^ */ if (!SCHEME_REALP(b)) scheme_wrong_type("fmod", "real number", 1, argc, argv); /* 2nd arg wrong ----^ */ /* Convert the Scheme numbers to double-precision floating point numbers, and compute fmod: */ v = fmod(scheme_real_to_double(a), scheme_real_to_double(b)); /* Return the result, packaging it as a Scheme value: */ return scheme_make_double(v); } /**************************************************/ Scheme_Object *scheme_reload(Scheme_Env *env) { Scheme_Object *proc; /* The MZ_GC... lines are for for 3m, because env is live across an allocating call. They're not needed for plain old (conservatively collected) Mzscheme. See makeadder3m.c for more info. */ MZ_GC_DECL_REG(1); MZ_GC_VAR_IN_REG(0, env); MZ_GC_REG(); /* Package the C implementation of fmod into a Scheme procedure value: */ proc = scheme_make_prim_w_arity(sch_fmod, "fmod", 2, 2); /* Requires at least two args ------^ ^ */ /* Accepts no more than two args ---| */ /* Define `fmod' as a global :*/ scheme_add_global("fmod", proc, env); MZ_GC_UNREG(); return scheme_void; } Scheme_Object *scheme_initialize(Scheme_Env *env) { /* First load is same as every load: */ return scheme_reload(env); } Scheme_Object *scheme_module_name() { /* This extension doesn't define a module: */ return scheme_false; }