aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/clojure/contrib/complex_numbers.clj48
-rw-r--r--src/clojure/contrib/test_contrib/complex_numbers.clj30
2 files changed, 66 insertions, 12 deletions
diff --git a/src/clojure/contrib/complex_numbers.clj b/src/clojure/contrib/complex_numbers.clj
index 1a05934a..942051da 100644
--- a/src/clojure/contrib/complex_numbers.clj
+++ b/src/clojure/contrib/complex_numbers.clj
@@ -1,7 +1,7 @@
;; Complex numbers
;; by Konrad Hinsen
-;; last updated March 23, 2009
+;; last updated April 2, 2009
;; Copyright (c) Konrad Hinsen, 2009. All rights reserved. The use
;; and distribution terms for this software are covered by the Eclipse
@@ -249,10 +249,42 @@
;
; Square root
;
-(defmethod gm/sqrt ::complex
- [{r :real i :imag}]
- (let [abs (gm/sqrt (ga/+ (ga/* r r) (ga/* i i)))
- p (gm/sqrt ((ga/qsym ga /) (ga/+ abs r) 2))
- q (ga/* (gm/sgn i)
- (gm/sqrt ((ga/qsym ga /) (ga/- abs r) 2)))]
- (complex p q)))
+(let [one-half (/ 1 2)
+ one-eighth (/ 1 8)]
+ (defmethod gm/sqrt ::complex
+ [x]
+ (let [[r i] (vals x)]
+ (if (and (gc/zero? r) (gc/zero? i))
+ 0
+ (let [; The basic formula would say
+ ; abs (gm/sqrt (ga/+ (ga/* r r) (ga/* i i)))
+ ; p (gm/sqrt (ga/* one-half (ga/+ abs r)))
+ ; but the slightly more complicated one below
+ ; avoids overflow for large r or i.
+ ar (gm/abs r)
+ ai (gm/abs i)
+ r8 (ga/* one-eighth ar)
+ i8 (ga/* one-eighth ai)
+ abs (gm/sqrt (ga/+ (ga/* r8 r8) (ga/* i8 i8)))
+ p (ga/* 2 (gm/sqrt (ga/+ abs r8)))
+ q ((ga/qsym ga /) ai (ga/* 2 p))
+ s (gm/sgn i)]
+ (if (gc/< r 0)
+ (complex q (ga/* s p))
+ (complex p (ga/* s q))))))))
+
+;
+; Exponential function
+;
+(defmethod gm/exp ::complex
+ [x]
+ (let [[r i] (vals x)
+ exp-r (gm/exp r)
+ cos-i (gm/cos i)
+ sin-i (gm/sin i)]
+ (complex (ga/* exp-r cos-i) (ga/* exp-r sin-i))))
+
+(defmethod gm/exp ::pure-imaginary
+ [x]
+ (let [i (imag x)]
+ (complex (gm/cos i) (gm/sin i))))
diff --git a/src/clojure/contrib/test_contrib/complex_numbers.clj b/src/clojure/contrib/test_contrib/complex_numbers.clj
index b8b03f49..2ac2ff86 100644
--- a/src/clojure/contrib/test_contrib/complex_numbers.clj
+++ b/src/clojure/contrib/test_contrib/complex_numbers.clj
@@ -1,7 +1,7 @@
;; Test routines for complex-numbers.clj
;; by Konrad Hinsen
-;; last updated March 23, 2009
+;; last updated April 2, 2009
;; Copyright (c) Konrad Hinsen, 2008. All rights reserved. The use
;; and distribution terms for this software are covered by the Eclipse
@@ -20,7 +20,7 @@
[clojure.contrib.generic.comparison
:only (= < > <= >=)]
[clojure.contrib.generic.math-functions
- :only (abs approx= conjugate sqr sqrt)]
+ :only (abs approx= conjugate exp sqr sqrt)]
[clojure.contrib.complex-numbers
:only (complex imaginary real imag)]))
@@ -279,13 +279,35 @@
(is (= (conjugate (imaginary 5)) (imaginary -5))))
(deftest complex-abs
- (doseq [c [(complex 1 2) (complex -3 -7) (imaginary -2) (imaginary 5)]]
+ (doseq [c [(complex 1 2) (complex -2 3) (complex 4 -2)
+ (complex -3 -7) (imaginary -2) (imaginary 5)]]
(is (approx= (* c (conjugate c))
(sqr (abs c))
1e-14))))
(deftest complex-sqrt
- (doseq [c [(complex 1 2) (complex -3 -7) (imaginary -2) (imaginary 5)]]
+ (doseq [c [(complex 1 2) (complex -2 3) (complex 4 -2)
+ (complex -3 -7) (imaginary -2) (imaginary 5)]]
(let [r (sqrt c)]
(is (approx= c (sqr r) 1e-14))
(is (>= (real r) 0)))))
+
+(deftest complex-exp
+ (is (approx= (exp (complex 1 2))
+ (complex -1.1312043837568135 2.4717266720048188)
+ 1e-14))
+ (is (approx= (exp (complex 2 3))
+ (complex -7.3151100949011028 1.0427436562359045)
+ 1e-14))
+ (is (approx= (exp (complex 4 -2))
+ (complex -22.720847417619233 -49.645957334580565)
+ 1e-14))
+ (is (approx= (exp (complex 3 -7))
+ (complex 15.142531566086868 -13.195928586605717)
+ 1e-14))
+ (is (approx= (exp (imaginary -2))
+ (complex -0.41614683654714241 -0.90929742682568171)
+ 1e-14))
+ (is (approx= (exp (imaginary 5))
+ (complex 0.2836621854632263 -0.95892427466313845)
+ 1e-14)))