root/trunk/mathematical.lisp

Revision 26, 6.7 kB (checked in by lhealy, 8 months ago)

Subversion version stamp.

  • Property svn:keywords set to Id
Line 
1;; Mathematical functions
2;; Liam Healy, Wed Mar  8 2006 - 22:09
3;; Time-stamp: <2008-02-17 09:13:19EST mathematical.lisp>
4;; $Id$
5
6(in-package :gsl)
7
8;;; Disable floating point traps for each CL implementation.
9
10;;; Not ported because they are all C macros or inline functions:
11;;;   Mathematical Constants
12;;;   Testing the Sign of Numbers
13;;;   Testing for Odd and Even Numbers
14;;;   Maximum and Minimum functions
15;;; Does CL need the small integer powers?
16
17;;;;****************************************************************************
18;;; Infinities and Not-a-number
19;;;;****************************************************************************
20
21(defmacro pmnil (x)
22  "+1, -1, or nil"
23  `(let ((v ,x))
24     (when (or (= 1 v) (= -1 v))
25       v)))
26
27#+sbcl
28(eval-when (:compile-toplevel :load-toplevel :execute)
29  (sb-int:set-floating-point-modes :traps nil)
30  (import
31   '(sb-ext:double-float-negative-infinity
32     sb-ext:double-float-positive-infinity)))
33
34(export '(+nan+ +positive-infinity+ +negative-infinity+))
35
36(defconstant +nan+
37  (ignore-errors
38    (cffi:foreign-funcall "gsl_nan" :double)))
39
40(defconstant +positive-infinity+
41  (ignore-errors
42    (cffi:foreign-funcall "gsl_posinf" :double)))
43
44(defconstant +negative-infinity+
45  (ignore-errors
46    (cffi:foreign-funcall "gsl_neginf" :double)))
47
48(defmfun nanp (x)
49  "gsl_isnan" ((x :double))
50  :c-return (cr :int)
51  :return ((= 1 cr))
52  :documentation                        ; FDL
53  "Return T if x is a double-float NaN.")
54
55(defmfun infinityp (x)
56  "gsl_isinf" ((x :double))
57  :c-return (cr :int)
58  :return ((pmnil cr))
59  :documentation                        ; FDL
60  "Return +1 if x is positive infinity, -1 if negative infinity
61   nil if finite.")
62
63(defmfun finitep (x)
64  "gsl_finite" ((x :double))
65  :c-return (cr :int)
66  :return ((= 1 cr))
67  :documentation                        ; FDL
68  "Return T if x is finite.")
69
70;;;;****************************************************************************
71;;; Elementary functions
72;;;;****************************************************************************
73
74(defmfun log+1 (x)
75  "gsl_log1p" ((x :double))
76  :c-return :double
77  :documentation                        ; FDL
78  "log(1+x), computed in a way that is accurate for small x.")
79
80(defmfun exp-1 (x)
81  "gsl_expm1" ((x :double))
82  :c-return :double
83  :documentation                        ; FDL
84  "exp(x)-1, computed in a way that is accurate for small x.")
85
86(defmfun hypotenuse* (x y)
87  ;; This is redundant; there is "gsl_sf_hypot_e" defined as
88  ;; #'hyptoenuse.
89  "gsl_hypot" ((x :double) (y :double))
90  :c-return :double
91  :documentation                        ;FDL
92  "The hypotenuse sqrt{x^2 + y^2} computed in a way that avoids overflow.")
93
94;; Not clear why this function exists
95(defmfun gsl-asinh (x)
96   "gsl_asinh" ((x :double))
97  :c-return :double
98  :documentation                        ; FDL
99  "Arc hyperbolic sine.")
100
101;; Not clear why this function exists
102(defmfun gsl-atanh (x)
103   "gsl_atanh" ((x :double))
104  :c-return :double
105  :documentation                        ; FDL
106  "Arc hyperbolic tangent.")
107
108;;; gsl_ldexp
109;;; gsl_frexp
110;;; not mapped because CL has equivalents.
111
112;;;;****************************************************************************
113;;; Small integer powers
114;;;;****************************************************************************
115
116;;; Does CL need these?
117
118#|
119;; FDL
120A common complaint about the standard C library is its lack of a
121function for calculating (small) integer powers. GSL provides a
122simple functions to fill this gap. For reasons of efficiency,
123these functions do not check for overflow or underflow
124conditions.
125
126Function: double gsl_pow_int (double x, int n)
127    This routine computes the power x^n for integer n. The power is computed efficiently--for example, x^8 is computed as ((x^2)^2)^2, requiring only 3 multiplications. A version of this function which also computes the numerical error in the result is available as gsl_sf_pow_int_e.
128
129Function: double gsl_pow_2 (const double x)
130Function: double gsl_pow_3 (const double x)
131Function: double gsl_pow_4 (const double x)
132Function: double gsl_pow_5 (const double x)
133Function: double gsl_pow_6 (const double x)
134Function: double gsl_pow_7 (const double x)
135Function: double gsl_pow_8 (const double x)
136Function: double gsl_pow_9 (const double x)
137    These functions can be used to compute small integer powers x^2, x^3, etc. efficiently. The functions will be inlined when possible so that use of these functions should be as efficient as explicitly writing the corresponding product expression.
138
139|#
140
141;;;; Testing the Sign of Numbers
142;;; is all macros
143
144;;;; Testing for Odd and Even Numbers
145;;; is all macros
146
147;;;; Maximum and Minimum functions
148;;; is all macros and inline functions that have CL equivalents
149
150;;;;****************************************************************************
151;;; Approximate Comparison of Floating Point Numbers
152;;;;****************************************************************************
153
154;;; FDL
155;;; It is sometimes useful to be able to compare two floating point
156;;; numbers approximately, to allow for rounding and truncation
157;;; errors. This function implements the approximate
158;;; floating-point comparison algorithm proposed by D.E. Knuth in
159;;; Section 4.2.2 of Seminumerical Algorithms (3rd edition).
160
161(defmfun double-float-unequal (x y epsilon)
162  "gsl_fcmp" ((x :double) (y :double) (epsilon :double))
163  :c-return (cr :int)
164  :documentation                        ; FDL
165  "This function determines whether x and y are approximately equal
166    to a relative accuracy epsilon.
167
168    The relative accuracy is measured using an interval of size 2
169    delta, where delta = 2^k \epsilon and k is the maximum
170    base-2 exponent of x and y as computed by the function
171    frexp().
172
173    If x and y lie within this interval, they are considered
174    approximately equal and the function returns nil. Otherwise if
175    x < y, the function returns -1, or if x > y, the function
176    returns +1."
177  :return ((pmnil cr)))
178
179;;;;****************************************************************************
180;;;; Examples and unit test
181;;;;****************************************************************************
182
183#|
184(make-tests mathematical
185  (log+1 0.001d0)
186  (exp-1 0.001d0)
187  (hypotenuse 3.0d0 4.0d0))
188|#
189
190(lisp-unit:define-test mathematical
191  (lisp-unit:assert-true (nanp +nan+))
192  (lisp-unit:assert-false (nanp 1.0d0))
193  (lisp-unit:assert-true (finitep 1.0d0))
194  (lisp-unit:assert-false (infinityp 1.0d0))
195  (lisp-unit:assert-eq 1 (infinityp +positive-infinity+))
196  (lisp-unit:assert-false (finitep +positive-infinity+))
197  (LISP-UNIT::ASSERT-NUMERICAL-EQUAL
198   (LIST 9.995003330835331d-4)
199   (MULTIPLE-VALUE-LIST (LOG+1 0.001d0)))
200  (LISP-UNIT::ASSERT-NUMERICAL-EQUAL
201   (LIST 0.0010005001667083417d0)
202   (MULTIPLE-VALUE-LIST (EXP-1 0.001d0)))
203  (LISP-UNIT::ASSERT-NUMERICAL-EQUAL
204   (LIST 5.0d0 2.220446049250313d-15)
205   (MULTIPLE-VALUE-LIST (HYPOTENUSE 3.0d0 4.0d0)))
206  (lisp-unit:assert-false (double-float-unequal 1.0d0 1.0d0 0.001d0)))
Note: See TracBrowser for help on using the browser.