I'm trying my hand a writing C extensions. I've done this for stuff like Matlab before, and was wondering how you do the usual checking of the arguments that are passed in from Guile. In the manual, 6.13.13.1 "C Support" has a few functions. libguile/numbers.h has a bunch more ... What I have is an extension function, sort of like the bessel function in the tutorial: https://www.gnu.org/software/guile/manual/html_node/A-Sample-Guile-Extension.html What I would like to do is verify that the first argument is an inexact number, larger than 0. How would I go about that? Perhaps some of it could be: SCM_REALP scm_misc_error Any tips?
Hi Tim!
I think you may try these functions:
scm_is_true
scm_is_real_p
scm_geq_p
Best regards.
On Sun, Feb 21, 2021 at 11:57 AM Tim Meehan <btmeehan@gmail.com> wrote:
> I'm trying my hand a writing C extensions.
> I've done this for stuff like Matlab before, and was wondering how you do
> the usual checking of the arguments that are passed in from Guile.
>
> In the manual, 6.13.13.1 "C Support" has a few functions.
> libguile/numbers.h has a bunch more ...
>
> What I have is an extension function, sort of like the bessel function in
> the tutorial:
>
> https://www.gnu.org/software/guile/manual/html_node/A-Sample-Guile-Extension.html
>
> What I would like to do is verify that the first argument is an inexact
> number, larger than 0. How would I go about that? Perhaps some of it could
> be:
> SCM_REALP
> scm_misc_error
>
> Any tips?
>
On Sat, 20 Feb 2021, Tim Meehan <btmeehan@gmail.com> wrote: > I'm trying my hand a writing C extensions. > I've done this for stuff like Matlab before, and was wondering how you do > the usual checking of the arguments that are passed in from Guile. > > In the manual, 6.13.13.1 "C Support" has a few functions. > libguile/numbers.h has a bunch more ... > > What I have is an extension function, sort of like the bessel function in > the tutorial: > https://www.gnu.org/software/guile/manual/html_node/A-Sample-Guile-Extension.html Usually I do this in 2 or 3 steps. 1. Define the primitive in C with raw arguments. 2. Make a wrapper of this primitive for Guile to use. Optionnaly do the arguments checking here or go to step 3. 3. Make a second wrapper in Scheme and check the arguments there. This wrapper will call wrapper in made in 2. Here's a full example: ---------------------------------------------------------------------- float c_sin(double x) { return sin(x); } SCM_DEFINE(c_sin_wrapper, "sin", 1, 0, 0, (SCM x), "My sine") { if (scm_is_number(x)) { return c_sin(scm_to_double(x)); } return SCM_BOOL_F; } ---------------------------------------------------------------------- > What I would like to do is verify that the first argument is an inexact > number, larger than 0. How would I go about that? Perhaps some of it > could For your example, use the following predicates: ---------------------------------------------------------------------- scm_is_inexact(x) && scm_is_true(scm_positive_p(x)) ---------------------------------------------------------------------- > be: > SCM_REALP > scm_misc_error > > Any tips? -- Olivier Dion PolyMtl
Hello Olivier, thanks!
Those functions helped, and now I know where in the source of Guile to look.
Is "inexact" the same thing as "floating point number" in Guile-speak?
Here is one of the functions in my extension - it returns a lognormal
variate. There are a bunch of things like this that could be added to
"random.c" - but I'm imagining that the only user of stuff like that might
be ... me ... anyhow:
Right now, it doesn't give really helpful errors when you give it a
negative standard deviation:
scheme@(guile-user)> (random:lognormal 0 -1)
$1 = #f
SCM_DEFINE (scm_random_lognormal, "random:lognormal", 2, 1, 0,
(SCM _mu, SCM _sigma, SCM state),
"Return an inexact real in a Log Normal distribution.\n"
"\n"
"@var{mu} - mean of the underlying normal distribution.\n"
"@var{sigma} - standard deviation of the same.\n"
"Optionally, a random @var{state} can be provided.\n"
"See @code{seed->random-state}.")
#define FUNC_NAME s_scm_random_lognormal
{
if (SCM_UNBNDP (state))
state = SCM_VARIABLE_REF (scm_var_random_state);
SCM_VALIDATE_RSTATE (1, state);
if (scm_is_false (scm_positive_p (_sigma)))
return SCM_BOOL_F; // I'd like to return some meaningful error here ...
double mu = scm_to_double (_mu);
double sigma = scm_to_double (_sigma);
return scm_from_double (exp (mu + sigma*scm_c_normal01
(SCM_RSTATE(state))));
}
#undef FUNC_NAME
On Sun, Feb 21, 2021 at 9:59 AM Olivier Dion <olivier.dion@polymtl.ca>
wrote:
> On Sat, 20 Feb 2021, Tim Meehan <btmeehan@gmail.com> wrote:
> > I'm trying my hand a writing C extensions.
> > I've done this for stuff like Matlab before, and was wondering how you do
> > the usual checking of the arguments that are passed in from Guile.
> >
> > In the manual, 6.13.13.1 "C Support" has a few functions.
> > libguile/numbers.h has a bunch more ...
> >
> > What I have is an extension function, sort of like the bessel function in
> > the tutorial:
> >
> https://www.gnu.org/software/guile/manual/html_node/A-Sample-Guile-Extension.html
>
> Usually I do this in 2 or 3 steps.
>
> 1. Define the primitive in C with raw arguments.
>
> 2. Make a wrapper of this primitive for Guile to use. Optionnaly do
> the arguments checking here or go to step 3.
>
> 3. Make a second wrapper in Scheme and check the arguments there.
> This wrapper will call wrapper in made in 2.
>
> Here's a full example:
> ----------------------------------------------------------------------
> float c_sin(double x)
> {
> return sin(x);
> }
>
> SCM_DEFINE(c_sin_wrapper, "sin", 1, 0, 0,
> (SCM x),
> "My sine")
> {
> if (scm_is_number(x)) {
> return c_sin(scm_to_double(x));
> }
>
> return SCM_BOOL_F;
> }
> ----------------------------------------------------------------------
>
> > What I would like to do is verify that the first argument is an inexact
> > number, larger than 0. How would I go about that? Perhaps some of it
> > could
>
> For your example, use the following predicates:
> ----------------------------------------------------------------------
> scm_is_inexact(x) && scm_is_true(scm_positive_p(x))
> ----------------------------------------------------------------------
>
> > be:
> > SCM_REALP
> > scm_misc_error
> >
> > Any tips?
> --
> Olivier Dion
> PolyMtl
>
I suppose that I could use something like "scm_wrong_type_arg_msg" ...
which gives better looking feedback than "#f":
scheme@(guile-user)> (random:lognormal 0 -1)
ice-9/boot-9.scm:1669:16: In procedure raise-exception:
In procedure random:lognormal: Wrong type argument in position 2 (expecting
standard deviation): -1
On Sun, Feb 21, 2021 at 3:58 PM Tim Meehan <btmeehan@gmail.com> wrote:
> Hello Olivier, thanks!
> Those functions helped, and now I know where in the source of Guile to
> look.
>
> Is "inexact" the same thing as "floating point number" in Guile-speak?
>
> Here is one of the functions in my extension - it returns a lognormal
> variate. There are a bunch of things like this that could be added to
> "random.c" - but I'm imagining that the only user of stuff like that might
> be ... me ... anyhow:
>
> Right now, it doesn't give really helpful errors when you give it a
> negative standard deviation:
> scheme@(guile-user)> (random:lognormal 0 -1)
> $1 = #f
>
> SCM_DEFINE (scm_random_lognormal, "random:lognormal", 2, 1, 0,
> (SCM _mu, SCM _sigma, SCM state),
> "Return an inexact real in a Log Normal distribution.\n"
> "\n"
> "@var{mu} - mean of the underlying normal distribution.\n"
> "@var{sigma} - standard deviation of the same.\n"
> "Optionally, a random @var{state} can be provided.\n"
> "See @code{seed->random-state}.")
> #define FUNC_NAME s_scm_random_lognormal
> {
> if (SCM_UNBNDP (state))
> state = SCM_VARIABLE_REF (scm_var_random_state);
> SCM_VALIDATE_RSTATE (1, state);
>
> if (scm_is_false (scm_positive_p (_sigma)))
> return SCM_BOOL_F; // I'd like to return some meaningful error here ...
>
> double mu = scm_to_double (_mu);
> double sigma = scm_to_double (_sigma);
> return scm_from_double (exp (mu + sigma*scm_c_normal01
> (SCM_RSTATE(state))));
> }
> #undef FUNC_NAME
>
> On Sun, Feb 21, 2021 at 9:59 AM Olivier Dion <olivier.dion@polymtl.ca>
> wrote:
>
>> On Sat, 20 Feb 2021, Tim Meehan <btmeehan@gmail.com> wrote:
>> > I'm trying my hand a writing C extensions.
>> > I've done this for stuff like Matlab before, and was wondering how you
>> do
>> > the usual checking of the arguments that are passed in from Guile.
>> >
>> > In the manual, 6.13.13.1 "C Support" has a few functions.
>> > libguile/numbers.h has a bunch more ...
>> >
>> > What I have is an extension function, sort of like the bessel function
>> in
>> > the tutorial:
>> >
>> https://www.gnu.org/software/guile/manual/html_node/A-Sample-Guile-Extension.html
>>
>> Usually I do this in 2 or 3 steps.
>>
>> 1. Define the primitive in C with raw arguments.
>>
>> 2. Make a wrapper of this primitive for Guile to use. Optionnaly do
>> the arguments checking here or go to step 3.
>>
>> 3. Make a second wrapper in Scheme and check the arguments there.
>> This wrapper will call wrapper in made in 2.
>>
>> Here's a full example:
>> ----------------------------------------------------------------------
>> float c_sin(double x)
>> {
>> return sin(x);
>> }
>>
>> SCM_DEFINE(c_sin_wrapper, "sin", 1, 0, 0,
>> (SCM x),
>> "My sine")
>> {
>> if (scm_is_number(x)) {
>> return c_sin(scm_to_double(x));
>> }
>>
>> return SCM_BOOL_F;
>> }
>> ----------------------------------------------------------------------
>>
>> > What I would like to do is verify that the first argument is an inexact
>> > number, larger than 0. How would I go about that? Perhaps some of it
>> > could
>>
>> For your example, use the following predicates:
>> ----------------------------------------------------------------------
>> scm_is_inexact(x) && scm_is_true(scm_positive_p(x))
>> ----------------------------------------------------------------------
>>
>> > be:
>> > SCM_REALP
>> > scm_misc_error
>> >
>> > Any tips?
>> --
>> Olivier Dion
>> PolyMtl
>>
>
On Sun, 21 Feb 2021, Tim Meehan <btmeehan@gmail.com> wrote: > Hello Olivier, thanks! > Those functions helped, and now I know where in the source of Guile to look. > > Is "inexact" the same thing as "floating point number" in Guile-speak? I don't think so. If I remember correctly, exact numbers are numbers that can be represented by a quotient of two integers. In other words, any rational number is an exact number. I might be wrong here. I highly suggest that you read the numerical tower from the Guile's texinfo manual for more informations on that. > > Here is one of the functions in my extension - it returns a lognormal > variate. There are a bunch of things like this that could be added to > "random.c" - but I'm imagining that the only user of stuff like that might > be ... me ... anyhow: > > Right now, it doesn't give really helpful errors when you give it a > negative standard deviation: > scheme@(guile-user)> (random:lognormal 0 -1) > $1 = #f In my example, I returned false because this is how I would approach the problem from a C perspective. i.e., returning an error code. I'm still learning on how to work with Scheme. I guess that if you want something more Pythonic, you would throw an exception. > SCM_DEFINE (scm_random_lognormal, "random:lognormal", 2, 1, 0, > (SCM _mu, SCM _sigma, SCM state), > "Return an inexact real in a Log Normal distribution.\n" > "\n" > "@var{mu} - mean of the underlying normal distribution.\n" > "@var{sigma} - standard deviation of the same.\n" > "Optionally, a random @var{state} can be provided.\n" > "See @code{seed->random-state}.") > #define FUNC_NAME s_scm_random_lognormal > { > if (SCM_UNBNDP (state)) > state = SCM_VARIABLE_REF (scm_var_random_state); > SCM_VALIDATE_RSTATE (1, state); > > if (scm_is_false (scm_positive_p (_sigma))) > return SCM_BOOL_F; // I'd like to return some meaningful error > here ... You can use `scm_throw()` to throw an exception. ---------------------------------------------------------------------- /* * This create a symbol that has static linkage in C. You might want * to declare it globally instead. */ SCM_SYMBOL(lognormal_error_key, "invalid-argument"); if (scm_is_false (scm_positive_p (_sigma))) { scm_throw(lognormal_error_key, scm_list_n(SCM_UNDEFINED)); /* Unreachable path! */ assert(0); } ---------------------------------------------------------------------- Note that throwing an error might be easier to do in Scheme itself: ---------------------------------------------------------------------- (throw 'invalid-argument) ---------------------------------------------------------------------- > > double mu = scm_to_double (_mu); > double sigma = scm_to_double (_sigma); > return scm_from_double (exp (mu + sigma*scm_c_normal01 > (SCM_RSTATE(state)))); > } > #undef FUNC_NAME > > On Sun, Feb 21, 2021 at 9:59 AM Olivier Dion <olivier.dion@polymtl.ca> > wrote: > >> On Sat, 20 Feb 2021, Tim Meehan <btmeehan@gmail.com> wrote: >> > I'm trying my hand a writing C extensions. >> > I've done this for stuff like Matlab before, and was wondering how you do >> > the usual checking of the arguments that are passed in from Guile. >> > >> > In the manual, 6.13.13.1 "C Support" has a few functions. >> > libguile/numbers.h has a bunch more ... >> > >> > What I have is an extension function, sort of like the bessel function in >> > the tutorial: >> > >> https://www.gnu.org/software/guile/manual/html_node/A-Sample-Guile-Extension.html >> >> Usually I do this in 2 or 3 steps. >> >> 1. Define the primitive in C with raw arguments. >> >> 2. Make a wrapper of this primitive for Guile to use. Optionnaly do >> the arguments checking here or go to step 3. >> >> 3. Make a second wrapper in Scheme and check the arguments there. >> This wrapper will call wrapper in made in 2. >> >> Here's a full example: >> ---------------------------------------------------------------------- >> float c_sin(double x) >> { >> return sin(x); >> } >> >> SCM_DEFINE(c_sin_wrapper, "sin", 1, 0, 0, >> (SCM x), >> "My sine") >> { >> if (scm_is_number(x)) { >> return c_sin(scm_to_double(x)); >> } >> >> return SCM_BOOL_F; >> } >> ---------------------------------------------------------------------- >> >> > What I would like to do is verify that the first argument is an inexact >> > number, larger than 0. How would I go about that? Perhaps some of it >> > could >> >> For your example, use the following predicates: >> ---------------------------------------------------------------------- >> scm_is_inexact(x) && scm_is_true(scm_positive_p(x)) >> ---------------------------------------------------------------------- >> >> > be: >> > SCM_REALP >> > scm_misc_error >> > >> > Any tips? >> -- >> Olivier Dion >> PolyMtl >> -- Olivier Dion PolyMtl