unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* C extensions
@ 2021-02-21  3:56 Tim Meehan
  2021-02-21  4:10 ` Nala Ginrut
  2021-02-21 16:00 ` Olivier Dion via General Guile related discussions
  0 siblings, 2 replies; 6+ messages in thread
From: Tim Meehan @ 2021-02-21  3:56 UTC (permalink / raw)
  To: guile-user

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?


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: C extensions
  2021-02-21  3:56 C extensions Tim Meehan
@ 2021-02-21  4:10 ` Nala Ginrut
  2021-02-21 16:00 ` Olivier Dion via General Guile related discussions
  1 sibling, 0 replies; 6+ messages in thread
From: Nala Ginrut @ 2021-02-21  4:10 UTC (permalink / raw)
  To: Tim Meehan; +Cc: guile-user

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?
>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: C extensions
  2021-02-21  3:56 C extensions Tim Meehan
  2021-02-21  4:10 ` Nala Ginrut
@ 2021-02-21 16:00 ` Olivier Dion via General Guile related discussions
  2021-02-21 21:58   ` Tim Meehan
  1 sibling, 1 reply; 6+ messages in thread
From: Olivier Dion via General Guile related discussions @ 2021-02-21 16:00 UTC (permalink / raw)
  To: Tim Meehan, guile-user

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



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: C extensions
  2021-02-21 16:00 ` Olivier Dion via General Guile related discussions
@ 2021-02-21 21:58   ` Tim Meehan
  2021-02-21 22:18     ` Tim Meehan
  2021-02-21 22:41     ` Olivier Dion via General Guile related discussions
  0 siblings, 2 replies; 6+ messages in thread
From: Tim Meehan @ 2021-02-21 21:58 UTC (permalink / raw)
  Cc: guile-user

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
>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: C extensions
  2021-02-21 21:58   ` Tim Meehan
@ 2021-02-21 22:18     ` Tim Meehan
  2021-02-21 22:41     ` Olivier Dion via General Guile related discussions
  1 sibling, 0 replies; 6+ messages in thread
From: Tim Meehan @ 2021-02-21 22:18 UTC (permalink / raw)
  Cc: guile-user

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
>>
>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: C extensions
  2021-02-21 21:58   ` Tim Meehan
  2021-02-21 22:18     ` Tim Meehan
@ 2021-02-21 22:41     ` Olivier Dion via General Guile related discussions
  1 sibling, 0 replies; 6+ messages in thread
From: Olivier Dion via General Guile related discussions @ 2021-02-21 22:41 UTC (permalink / raw)
  To: Tim Meehan; +Cc: guile-user

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



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-02-21 22:41 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-21  3:56 C extensions Tim Meehan
2021-02-21  4:10 ` Nala Ginrut
2021-02-21 16:00 ` Olivier Dion via General Guile related discussions
2021-02-21 21:58   ` Tim Meehan
2021-02-21 22:18     ` Tim Meehan
2021-02-21 22:41     ` Olivier Dion via General Guile related discussions

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).