unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* log10 etc in C
@ 2006-09-07 23:06 Kevin Ryde
  2006-09-07 23:12 ` Pat Lasswell
  0 siblings, 1 reply; 2+ messages in thread
From: Kevin Ryde @ 2006-09-07 23:06 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 196 bytes --]

I'm looking at moving some of log, log10, etc from boot-9.scm into
numbers.c.  For log10 it means using the log10() func directly, and
for the others gives the chance to use the libc clog() etc.


[-- Attachment #2: numbers.c.clog.diff --]
[-- Type: text/plain, Size: 4638 bytes --]

--- numbers.c.~1.281.2.4.~	2006-07-13 11:35:24.000000000 +1000
+++ numbers.c	2006-09-08 09:02:11.000000000 +1000
@@ -40,7 +40,7 @@
 
  */
 
-/* tell glibc (2.3) to give prototype for C99 trunc() */
+/* tell glibc (2.3) to give prototype for C99 trunc(), csqrt(), etc */
 #define _GNU_SOURCE
 
 #if HAVE_CONFIG_H
@@ -51,6 +51,10 @@
 #include <ctype.h>
 #include <string.h>
 
+#if HAVE_COMPLEX_H
+#include <complex.h>
+#endif
+
 #include "libguile/_scm.h"
 #include "libguile/feature.h"
 #include "libguile/ports.h"
@@ -66,6 +70,11 @@
 
 #include "libguile/discouraged.h"
 
+/* value per glibc, if not already defined */
+#ifndef M_LOG10E
+#define M_LOG10E   0.43429448190325182765
+#endif
+
 \f
 
 /*
@@ -150,6 +159,21 @@
 #endif
 }
 
+#if HAVE_COMPLEX_DOUBLE
+
+/* For an SCM object Z which is a complex number (ie. satisfies
+   SCM_COMPLEXP), return its value as a C level "_Complex double". */
+#define SCM_COMPLEX_VALUE(z)                                    \
+  (SCM_COMPLEX_REAL (z) + _Complex_I * SCM_COMPLEX_IMAG (z))
+
+static SCM
+scm_from_complex_double (_Complex double z)
+{
+  return scm_c_make_rectangular (creal (z), cimag (z));
+}
+
+#endif /* HAVE_COMPLEX_DOUBLE */
+
 \f
 
 static mpz_t z_negative_one;
@@ -5977,6 +6001,122 @@
   return scm_is_true (scm_number_p (z));
 }
 
+
+/* In the following it might save a bit of code to use scm_to_complex_double
+   and call the "clog" or whatever function for both real and complex
+   values.  But that's not done in case the complex funcs aren't optimized
+   to look for real-only arguments.  We have to test SCM_COMPLEXP anyway, so
+   may as well use that test to dispatch direct to the real or complex libc
+   function.  */
+
+SCM_DEFINE (scm_log, "log", 1, 0, 0,
+            (SCM z),
+	    "Return the natural logarithm of @var{z}.")
+#define FUNC_NAME s_scm_log
+{
+  if (SCM_COMPLEXP (z))
+    {
+#if HAVE_COMPLEX_DOUBLE
+      return scm_from_complex_double (clog (SCM_COMPLEX_VALUE (z)));
+#else
+      double re = SCM_COMPLEX_REAL (z);
+      double im = SCM_COMPLEX_IMAG (z);
+      return scm_c_make_rectangular (log (hypot (re, im)),
+                                     atan2 (im, re));
+#endif
+    }
+  else
+    {
+      /* ENHANCE-ME: When z is a bignum the logarithm will fit a double
+         although the value itself overflows.  */
+      return scm_from_double (log (scm_to_double (z)));
+    }
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_log10, "log10", 1, 0, 0,
+            (SCM z),
+	    "Return the base 10 logarithm of @var{z}.")
+#define FUNC_NAME s_scm_log10
+{
+  if (SCM_COMPLEXP (z))
+    {
+#if HAVE_COMPLEX_DOUBLE
+      return scm_from_complex_double (clog10 (SCM_COMPLEX_VALUE (z)));
+#else
+      double re = SCM_COMPLEX_REAL (z);
+      double im = SCM_COMPLEX_IMAG (z);
+      return scm_c_make_rectangular (log10 (hypot (re, im)),
+                                     M_LOG10E * atan2 (im, re));
+#endif
+    }
+  else
+    {
+      /* ENHANCE-ME: When z is a bignum the logarithm will fit a double
+         although the value itself overflows.  */
+      return scm_from_double (log10 (scm_to_double (z)));
+    }
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_exp, "exp", 1, 0, 0,
+            (SCM z),
+	    "Return @math{e} to the power of @var{z}, where @math{e} is the\n"
+	    "base of natural logarithms (2.71828@dots{}).")
+#define FUNC_NAME s_scm_exp
+{
+  if (SCM_COMPLEXP (z))
+    {
+#if HAVE_COMPLEX_DOUBLE
+      return scm_from_complex_double (cexp (SCM_COMPLEX_VALUE (z)));
+#else
+      double re = SCM_COMPLEX_REAL (z);
+      double im = SCM_COMPLEX_IMAG (z);
+      double ee = exp (re);
+      return scm_c_make_rectangular (ee * cos(im), ee * sin(im));
+#endif
+    }
+  else
+    {
+      /* When z is a negative bignum, conversion to double overflows, giving
+         -inf, but that's ok, the exp is still 0.0.  */
+      return scm_from_double (exp (scm_to_double (z)));
+    }
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_sqrt, "sqrt", 1, 0, 0,
+            (SCM x),
+            "")
+#define FUNC_NAME s_scm_sqrt
+{
+  if (SCM_COMPLEXP (x))
+    {
+#if HAVE_COMPLEX_DOUBLE
+      return scm_from_complex_double (csqrt (SCM_COMPLEX_VALUE (x)));
+#else
+      double re = SCM_COMPLEX_REAL (x);
+      double im = SCM_COMPLEX_IMAG (x);
+      return scm_c_make_polar (sqrt (hypot (re, im)),
+                               0.5 * atan2 (im, re));
+#endif
+    }
+  else
+    {
+      double xx = scm_to_double (x);
+      if (xx < 0)
+        return scm_c_make_rectangular (0.0, sqrt (-xx));
+      else
+        return scm_from_double (sqrt (xx));
+    }
+}
+#undef FUNC_NAME
+
+
+
 void
 scm_init_numbers ()
 {

[-- Attachment #3: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

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

* Re: log10 etc in C
  2006-09-07 23:06 log10 etc in C Kevin Ryde
@ 2006-09-07 23:12 ` Pat Lasswell
  0 siblings, 0 replies; 2+ messages in thread
From: Pat Lasswell @ 2006-09-07 23:12 UTC (permalink / raw)



[-- Attachment #1.1: Type: text/plain, Size: 5603 bytes --]

Since libmath exists probably most everywhere guile runs, does it make sense
to build an extension wrapping selected contents of math.h and then use
(load-extension ...) in boot-9?

pat

On 9/7/06, Kevin Ryde <user42@zip.com.au> wrote:
>
> I'm looking at moving some of log, log10, etc from boot-9.scm into
> numbers.c.  For log10 it means using the log10() func directly, and
> for the others gives the chance to use the libc clog() etc.
>
>
>
> --- numbers.c.~1.281.2.4.~      2006-07-13 11:35:24.000000000 +1000
> +++ numbers.c   2006-09-08 09:02:11.000000000 +1000
> @@ -40,7 +40,7 @@
>
>   */
>
> -/* tell glibc (2.3) to give prototype for C99 trunc() */
> +/* tell glibc (2.3) to give prototype for C99 trunc(), csqrt(), etc */
> #define _GNU_SOURCE
>
> #if HAVE_CONFIG_H
> @@ -51,6 +51,10 @@
> #include <ctype.h>
> #include <string.h>
>
> +#if HAVE_COMPLEX_H
> +#include <complex.h>
> +#endif
> +
> #include "libguile/_scm.h"
> #include "libguile/feature.h"
> #include "libguile/ports.h"
> @@ -66,6 +70,11 @@
>
> #include "libguile/discouraged.h"
>
> +/* value per glibc, if not already defined */
> +#ifndef M_LOG10E
> +#define M_LOG10E   0.43429448190325182765
> +#endif
> +
>
>
> /*
> @@ -150,6 +159,21 @@
> #endif
> }
>
> +#if HAVE_COMPLEX_DOUBLE
> +
> +/* For an SCM object Z which is a complex number (ie. satisfies
> +   SCM_COMPLEXP), return its value as a C level "_Complex double". */
> +#define SCM_COMPLEX_VALUE(z)                                    \
> +  (SCM_COMPLEX_REAL (z) + _Complex_I * SCM_COMPLEX_IMAG (z))
> +
> +static SCM
> +scm_from_complex_double (_Complex double z)
> +{
> +  return scm_c_make_rectangular (creal (z), cimag (z));
> +}
> +
> +#endif /* HAVE_COMPLEX_DOUBLE */
> +
>
>
> static mpz_t z_negative_one;
> @@ -5977,6 +6001,122 @@
>    return scm_is_true (scm_number_p (z));
> }
>
> +
> +/* In the following it might save a bit of code to use
> scm_to_complex_double
> +   and call the "clog" or whatever function for both real and complex
> +   values.  But that's not done in case the complex funcs aren't
> optimized
> +   to look for real-only arguments.  We have to test SCM_COMPLEXP anyway,
> so
> +   may as well use that test to dispatch direct to the real or complex
> libc
> +   function.  */
> +
> +SCM_DEFINE (scm_log, "log", 1, 0, 0,
> +            (SCM z),
> +           "Return the natural logarithm of @var{z}.")
> +#define FUNC_NAME s_scm_log
> +{
> +  if (SCM_COMPLEXP (z))
> +    {
> +#if HAVE_COMPLEX_DOUBLE
> +      return scm_from_complex_double (clog (SCM_COMPLEX_VALUE (z)));
> +#else
> +      double re = SCM_COMPLEX_REAL (z);
> +      double im = SCM_COMPLEX_IMAG (z);
> +      return scm_c_make_rectangular (log (hypot (re, im)),
> +                                     atan2 (im, re));
> +#endif
> +    }
> +  else
> +    {
> +      /* ENHANCE-ME: When z is a bignum the logarithm will fit a double
> +         although the value itself overflows.  */
> +      return scm_from_double (log (scm_to_double (z)));
> +    }
> +}
> +#undef FUNC_NAME
> +
> +
> +SCM_DEFINE (scm_log10, "log10", 1, 0, 0,
> +            (SCM z),
> +           "Return the base 10 logarithm of @var{z}.")
> +#define FUNC_NAME s_scm_log10
> +{
> +  if (SCM_COMPLEXP (z))
> +    {
> +#if HAVE_COMPLEX_DOUBLE
> +      return scm_from_complex_double (clog10 (SCM_COMPLEX_VALUE (z)));
> +#else
> +      double re = SCM_COMPLEX_REAL (z);
> +      double im = SCM_COMPLEX_IMAG (z);
> +      return scm_c_make_rectangular (log10 (hypot (re, im)),
> +                                     M_LOG10E * atan2 (im, re));
> +#endif
> +    }
> +  else
> +    {
> +      /* ENHANCE-ME: When z is a bignum the logarithm will fit a double
> +         although the value itself overflows.  */
> +      return scm_from_double (log10 (scm_to_double (z)));
> +    }
> +}
> +#undef FUNC_NAME
> +
> +
> +SCM_DEFINE (scm_exp, "exp", 1, 0, 0,
> +            (SCM z),
> +           "Return @math{e} to the power of @var{z}, where @math{e} is
> the\n"
> +           "base of natural logarithms (2.71828@dots{}).")
> +#define FUNC_NAME s_scm_exp
> +{
> +  if (SCM_COMPLEXP (z))
> +    {
> +#if HAVE_COMPLEX_DOUBLE
> +      return scm_from_complex_double (cexp (SCM_COMPLEX_VALUE (z)));
> +#else
> +      double re = SCM_COMPLEX_REAL (z);
> +      double im = SCM_COMPLEX_IMAG (z);
> +      double ee = exp (re);
> +      return scm_c_make_rectangular (ee * cos(im), ee * sin(im));
> +#endif
> +    }
> +  else
> +    {
> +      /* When z is a negative bignum, conversion to double overflows,
> giving
> +         -inf, but that's ok, the exp is still 0.0.  */
> +      return scm_from_double (exp (scm_to_double (z)));
> +    }
> +}
> +#undef FUNC_NAME
> +
> +
> +SCM_DEFINE (scm_sqrt, "sqrt", 1, 0, 0,
> +            (SCM x),
> +            "")
> +#define FUNC_NAME s_scm_sqrt
> +{
> +  if (SCM_COMPLEXP (x))
> +    {
> +#if HAVE_COMPLEX_DOUBLE
> +      return scm_from_complex_double (csqrt (SCM_COMPLEX_VALUE (x)));
> +#else
> +      double re = SCM_COMPLEX_REAL (x);
> +      double im = SCM_COMPLEX_IMAG (x);
> +      return scm_c_make_polar (sqrt (hypot (re, im)),
> +                               0.5 * atan2 (im, re));
> +#endif
> +    }
> +  else
> +    {
> +      double xx = scm_to_double (x);
> +      if (xx < 0)
> +        return scm_c_make_rectangular (0.0, sqrt (-xx));
> +      else
> +        return scm_from_double (sqrt (xx));
> +    }
> +}
> +#undef FUNC_NAME
> +
> +
> +
> void
> scm_init_numbers ()
> {
>
>
> _______________________________________________
> Guile-devel mailing list
> Guile-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/guile-devel
>
>
>

[-- Attachment #1.2: Type: text/html, Size: 9186 bytes --]

[-- Attachment #2: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

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

end of thread, other threads:[~2006-09-07 23:12 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-07 23:06 log10 etc in C Kevin Ryde
2006-09-07 23:12 ` Pat Lasswell

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