Mercurial > lasercutter
comparison src/clojure/contrib/complex_numbers.clj @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
9:35cf337adfcf | 10:ef7dbbd6452c |
---|---|
1 ;; Complex numbers | |
2 | |
3 ;; by Konrad Hinsen | |
4 ;; last updated May 4, 2009 | |
5 | |
6 ;; Copyright (c) Konrad Hinsen, 2009. All rights reserved. The use | |
7 ;; and distribution terms for this software are covered by the Eclipse | |
8 ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) | |
9 ;; which can be found in the file epl-v10.html at the root of this | |
10 ;; distribution. By using this software in any fashion, you are | |
11 ;; agreeing to be bound by the terms of this license. You must not | |
12 ;; remove this notice, or any other, from this software. | |
13 | |
14 (ns | |
15 ^{:author "Konrad Hinsen" | |
16 :doc "Complex numbers | |
17 NOTE: This library is in evolution. Most math functions are | |
18 not implemented yet."} | |
19 clojure.contrib.complex-numbers | |
20 (:refer-clojure :exclude (deftype)) | |
21 (:use [clojure.contrib.types :only (deftype)] | |
22 [clojure.contrib.generic :only (root-type)]) | |
23 (:require [clojure.contrib.generic.arithmetic :as ga] | |
24 [clojure.contrib.generic.comparison :as gc] | |
25 [clojure.contrib.generic.math-functions :as gm])) | |
26 | |
27 ; | |
28 ; Complex numbers are represented as struct maps. The real and imaginary | |
29 ; parts can be of any type for which arithmetic and maths functions | |
30 ; are defined. | |
31 ; | |
32 (defstruct complex-struct :real :imag) | |
33 | |
34 ; | |
35 ; The general complex number type | |
36 ; | |
37 (deftype ::complex complex | |
38 (fn [real imag] (struct complex-struct real imag)) | |
39 (fn [c] (vals c))) | |
40 | |
41 (derive ::complex root-type) | |
42 | |
43 ; | |
44 ; A specialized subtype for pure imaginary numbers. Introducing this type | |
45 ; reduces the number of operations by eliminating additions with and | |
46 ; multiplications by zero. | |
47 ; | |
48 (deftype ::pure-imaginary imaginary | |
49 (fn [imag] (struct complex-struct 0 imag)) | |
50 (fn [c] (list (:imag c)))) | |
51 | |
52 (derive ::pure-imaginary ::complex) | |
53 | |
54 ; | |
55 ; Extraction of real and imaginary parts | |
56 ; | |
57 (def real (accessor complex-struct :real)) | |
58 (def imag (accessor complex-struct :imag)) | |
59 | |
60 ; | |
61 ; Equality and zero test | |
62 ; | |
63 (defmethod gc/zero? ::complex | |
64 [x] | |
65 (let [[rx ix] (vals x)] | |
66 (and (zero? rx) (zero? ix)))) | |
67 | |
68 (defmethod gc/= [::complex ::complex] | |
69 [x y] | |
70 (let [[rx ix] (vals x) | |
71 [ry iy] (vals y)] | |
72 (and (gc/= rx ry) (gc/= ix iy)))) | |
73 | |
74 (defmethod gc/= [::pure-imaginary ::pure-imaginary] | |
75 [x y] | |
76 (gc/= (imag x) (imag y))) | |
77 | |
78 (defmethod gc/= [::complex ::pure-imaginary] | |
79 [x y] | |
80 (let [[rx ix] (vals x)] | |
81 (and (gc/zero? rx) (gc/= ix (imag y))))) | |
82 | |
83 (defmethod gc/= [::pure-imaginary ::complex] | |
84 [x y] | |
85 (let [[ry iy] (vals y)] | |
86 (and (gc/zero? ry) (gc/= (imag x) iy)))) | |
87 | |
88 (defmethod gc/= [::complex root-type] | |
89 [x y] | |
90 (let [[rx ix] (vals x)] | |
91 (and (gc/zero? ix) (gc/= rx y)))) | |
92 | |
93 (defmethod gc/= [root-type ::complex] | |
94 [x y] | |
95 (let [[ry iy] (vals y)] | |
96 (and (gc/zero? iy) (gc/= x ry)))) | |
97 | |
98 (defmethod gc/= [::pure-imaginary root-type] | |
99 [x y] | |
100 (and (gc/zero? (imag x)) (gc/zero? y))) | |
101 | |
102 (defmethod gc/= [root-type ::pure-imaginary] | |
103 [x y] | |
104 (and (gc/zero? x) (gc/zero? (imag y)))) | |
105 | |
106 ; | |
107 ; Addition | |
108 ; | |
109 (defmethod ga/+ [::complex ::complex] | |
110 [x y] | |
111 (let [[rx ix] (vals x) | |
112 [ry iy] (vals y)] | |
113 (complex (ga/+ rx ry) (ga/+ ix iy)))) | |
114 | |
115 (defmethod ga/+ [::pure-imaginary ::pure-imaginary] | |
116 [x y] | |
117 (imaginary (ga/+ (imag x) (imag y)))) | |
118 | |
119 (defmethod ga/+ [::complex ::pure-imaginary] | |
120 [x y] | |
121 (let [[rx ix] (vals x)] | |
122 (complex rx (ga/+ ix (imag y))))) | |
123 | |
124 (defmethod ga/+ [::pure-imaginary ::complex] | |
125 [x y] | |
126 (let [[ry iy] (vals y)] | |
127 (complex ry (ga/+ (imag x) iy)))) | |
128 | |
129 (defmethod ga/+ [::complex root-type] | |
130 [x y] | |
131 (let [[rx ix] (vals x)] | |
132 (complex (ga/+ rx y) ix))) | |
133 | |
134 (defmethod ga/+ [root-type ::complex] | |
135 [x y] | |
136 (let [[ry iy] (vals y)] | |
137 (complex (ga/+ x ry) iy))) | |
138 | |
139 (defmethod ga/+ [::pure-imaginary root-type] | |
140 [x y] | |
141 (complex y (imag x))) | |
142 | |
143 (defmethod ga/+ [root-type ::pure-imaginary] | |
144 [x y] | |
145 (complex x (imag y))) | |
146 | |
147 ; | |
148 ; Negation | |
149 ; | |
150 (defmethod ga/- ::complex | |
151 [x] | |
152 (let [[rx ix] (vals x)] | |
153 (complex (ga/- rx) (ga/- ix)))) | |
154 | |
155 (defmethod ga/- ::pure-imaginary | |
156 [x] | |
157 (imaginary (ga/- (imag x)))) | |
158 | |
159 ; | |
160 ; Subtraction is automatically supplied by ga/-, optimized implementations | |
161 ; can be added later... | |
162 ; | |
163 | |
164 ; | |
165 ; Multiplication | |
166 ; | |
167 (defmethod ga/* [::complex ::complex] | |
168 [x y] | |
169 (let [[rx ix] (vals x) | |
170 [ry iy] (vals y)] | |
171 (complex (ga/- (ga/* rx ry) (ga/* ix iy)) | |
172 (ga/+ (ga/* rx iy) (ga/* ix ry))))) | |
173 | |
174 (defmethod ga/* [::pure-imaginary ::pure-imaginary] | |
175 [x y] | |
176 (ga/- (ga/* (imag x) (imag y)))) | |
177 | |
178 (defmethod ga/* [::complex ::pure-imaginary] | |
179 [x y] | |
180 (let [[rx ix] (vals x) | |
181 iy (imag y)] | |
182 (complex (ga/- (ga/* ix iy)) | |
183 (ga/* rx iy)))) | |
184 | |
185 (defmethod ga/* [::pure-imaginary ::complex] | |
186 [x y] | |
187 (let [ix (imag x) | |
188 [ry iy] (vals y)] | |
189 (complex (ga/- (ga/* ix iy)) | |
190 (ga/* ix ry)))) | |
191 | |
192 (defmethod ga/* [::complex root-type] | |
193 [x y] | |
194 (let [[rx ix] (vals x)] | |
195 (complex (ga/* rx y) (ga/* ix y)))) | |
196 | |
197 (defmethod ga/* [root-type ::complex] | |
198 [x y] | |
199 (let [[ry iy] (vals y)] | |
200 (complex (ga/* x ry) (ga/* x iy)))) | |
201 | |
202 (defmethod ga/* [::pure-imaginary root-type] | |
203 [x y] | |
204 (imaginary (ga/* (imag x) y))) | |
205 | |
206 (defmethod ga/* [root-type ::pure-imaginary] | |
207 [x y] | |
208 (imaginary (ga/* x (imag y)))) | |
209 | |
210 ; | |
211 ; Inversion | |
212 ; | |
213 (ga/defmethod* ga / ::complex | |
214 [x] | |
215 (let [[rx ix] (vals x) | |
216 den ((ga/qsym ga /) (ga/+ (ga/* rx rx) (ga/* ix ix)))] | |
217 (complex (ga/* rx den) (ga/- (ga/* ix den))))) | |
218 | |
219 (ga/defmethod* ga / ::pure-imaginary | |
220 [x] | |
221 (imaginary (ga/- ((ga/qsym ga /) (imag x))))) | |
222 | |
223 ; | |
224 ; Division is automatically supplied by ga//, optimized implementations | |
225 ; can be added later... | |
226 ; | |
227 | |
228 ; | |
229 ; Conjugation | |
230 ; | |
231 (defmethod gm/conjugate ::complex | |
232 [x] | |
233 (let [[r i] (vals x)] | |
234 (complex r (ga/- i)))) | |
235 | |
236 (defmethod gm/conjugate ::pure-imaginary | |
237 [x] | |
238 (imaginary (ga/- (imag x)))) | |
239 | |
240 ; | |
241 ; Absolute value | |
242 ; | |
243 (defmethod gm/abs ::complex | |
244 [x] | |
245 (let [[r i] (vals x)] | |
246 (gm/sqrt (ga/+ (ga/* r r) (ga/* i i))))) | |
247 | |
248 (defmethod gm/abs ::pure-imaginary | |
249 [x] | |
250 (gm/abs (imag x))) | |
251 | |
252 ; | |
253 ; Square root | |
254 ; | |
255 (let [one-half (/ 1 2) | |
256 one-eighth (/ 1 8)] | |
257 (defmethod gm/sqrt ::complex | |
258 [x] | |
259 (let [[r i] (vals x)] | |
260 (if (and (gc/zero? r) (gc/zero? i)) | |
261 0 | |
262 (let [; The basic formula would say | |
263 ; abs (gm/sqrt (ga/+ (ga/* r r) (ga/* i i))) | |
264 ; p (gm/sqrt (ga/* one-half (ga/+ abs r))) | |
265 ; but the slightly more complicated one below | |
266 ; avoids overflow for large r or i. | |
267 ar (gm/abs r) | |
268 ai (gm/abs i) | |
269 r8 (ga/* one-eighth ar) | |
270 i8 (ga/* one-eighth ai) | |
271 abs (gm/sqrt (ga/+ (ga/* r8 r8) (ga/* i8 i8))) | |
272 p (ga/* 2 (gm/sqrt (ga/+ abs r8))) | |
273 q ((ga/qsym ga /) ai (ga/* 2 p)) | |
274 s (gm/sgn i)] | |
275 (if (gc/< r 0) | |
276 (complex q (ga/* s p)) | |
277 (complex p (ga/* s q)))))))) | |
278 | |
279 ; | |
280 ; Exponential function | |
281 ; | |
282 (defmethod gm/exp ::complex | |
283 [x] | |
284 (let [[r i] (vals x) | |
285 exp-r (gm/exp r) | |
286 cos-i (gm/cos i) | |
287 sin-i (gm/sin i)] | |
288 (complex (ga/* exp-r cos-i) (ga/* exp-r sin-i)))) | |
289 | |
290 (defmethod gm/exp ::pure-imaginary | |
291 [x] | |
292 (let [i (imag x)] | |
293 (complex (gm/cos i) (gm/sin i)))) |