-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathfourier.lisp
160 lines (135 loc) · 5.93 KB
/
fourier.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
;;; -*- Mode:Lisp; Package:Weyli; Base:10; Lowercase:T; Syntax:Common-Lisp -*-
;;; ===========================================================================
;;; Fourier Transforms
;;; ===========================================================================
;;; (c) Copyright 1989, 1993 Cornell University
;;; fourier.lisp,v 1.3 1994/11/15 19:55:25 rz Exp
(in-package :weyli)
;;; DELETE (make::adjust-version-numbers Weyl "1.3")
(defgeneric make-ge-fourier (domain argument svar fvar)
(:documentation
"The purpose of this method is not known."))
(defmethod make-ge-fourier ((domain general-expressions) argument svar fvar)
(make-instance 'ge-fourier :domain domain :argument argument
:space-var svar :freq-var fvar))
(defmethod print-object ((expr ge-fourier) stream)
(format stream "Four{~S, ~S->~S}"
(argument-of expr) (space-var-of expr) (freq-var-of expr)))
(defmethod ge-equal ((x ge-fourier) (y ge-fourier))
(and (ge-equal (argument-of x) (argument-of y))
(ge-equal (space-var-of x) (space-var-of y))
(ge-equal (freq-var-of x) (freq-var-of y))))
(defmethod ge-great ((x ge-fourier) (y ge-fourier))
(cond ((ge-great (argument-of x) (argument-of y)) t)
((ge-great (argument-of y) (argument-of x)) nil)
((ge-great (space-var-of x) (space-var-of y)) t)
((ge-great (space-var-of y) (space-var-of x)) nil)
((ge-great (freq-var-of x) (freq-var-of y)) t)))
(defgeneric ge-fourier (exp svar fvar)
(:documentation
"The purpose of this method is unknown.")
(:method (exp svar fvar)
(declare (ignore fvar))
(error "Don't know how to take the Fourier transform of ~S wrt ~S"
exp svar)))
(defmethod ge-fourier ((exp general-expression) (svar symbol) (fvar symbol))
(ge-fourier exp (coerce svar (domain-of exp)) (coerce fvar (domain-of exp))))
(defmethod ge-fourier (exp (svar ge-variable) (fvar ge-variable))
(make-ge-fourier (domain-of svar) (coerce exp (domain-of svar)) svar fvar))
(defmethod ge-fourier ((exp numeric) (svar ge-variable) (fvar ge-variable))
exp)
(defmethod ge-fourier ((exp ge-variable) (svar ge-variable) (fvar ge-variable))
(let ((domain (domain-of exp)))
(unless (and (eql domain (domain-of svar))
(eql domain (domain-of fvar)))
(error "Taking Fourier transform from different domains"))
(cond ((ge-equal exp svar) fvar)
((depends-on? exp svar)
(make-ge-fourier domain exp svar fvar))
(t exp))))
(defmethod ge-fourier ((exp ge-plus) (svar ge-variable) (fvar ge-variable))
(let ((domain (domain-of exp)))
(cond ((and (eql domain (domain-of svar))
(eql domain (domain-of fvar)))
(call-next-method))
(t (simplify
(make-ge-plus domain
(loop for x in (terms-of exp)
collect (ge-fourier x svar fvar))))))))
(defmethod ge-fourier ((exp ge-times) (svar ge-variable) (fvar ge-variable))
(let ((domain (domain-of exp))
terms depend-term free-terms)
(unless (and (eql domain (domain-of svar))
(eql domain (domain-of fvar)))
(error "Taking Fourier transform from different domains"))
(setq terms (terms-of exp))
(loop for term in terms
do (when (depends-on? term svar)
(cond ((null depend-term)
(setq depend-term term))
(t (return (setq free-terms :non-linear)))))
finally (setq free-terms
(remove depend-term terms)))
(cond ((eql free-terms :non-linear)
(make-ge-fourier domain exp svar fvar))
((null depend-term)
exp)
(t (simplify
(make-ge-times domain
(cons (ge-fourier depend-term svar fvar)
free-terms)))))))
#+ignore
(defmethod ge-fourier ((exp ge-deriv) (svar ge-variable) (fvar ge-variable))
(let ((domain (domain-of exp)))
(unless (and (eql domain (domain-of svar))
(eql domain (domain-of fvar)))
(error "Taking Fourier transform from different domains"))
(loop for entry in (varlist-of exp)
with varlist
do (when (ge-equal svar (first entry))
(setq varlist (remove entry (varlist-of exp)))
(return
(simplify
(* (expt fvar (second entry))
(if (null varlist)
(ge-fourier (argument-of exp) svar fvar)
(make-ge-deriv domain
(ge-fourier (argument-of exp) svar fvar)
varlist))))))
finally
(return
(simplify
(make-ge-deriv domain
(ge-fourier exp svar fvar)
(varlist-of exp)))))))
(defgeneric fourier (expression &rest variables)
(:documentation
"The purpose of this method is unknown."))
(defmethod fourier ((exp number) &rest vars)
(declare (ignore vars))
(make-element *general* exp))
(defmethod fourier ((exp numeric) &rest vars)
(declare (ignore vars))
exp)
(defmethod fourier ((exp symbol) &rest vars)
(setq exp (coerce exp *general*))
(loop for (sv fv) on vars by #'cddr
do (setq exp (ge-fourier exp (coerce sv *general*)
(coerce fv *general*))))
exp)
(defmethod fourier ((exp general-expression) &rest vars)
(setq exp (coerce exp *general*))
(loop for (sv fv) on vars by #'cddr
do (setq exp (ge-fourier exp (coerce sv *general*)
(coerce fv *general*))))
exp)
;; Inverse Fourier Transforms
(defgeneric make-ge-ifourier (domain argument svar fvar)
(:documentation
"The purpose of this method is unknown."))
(defmethod make-ge-ifourier ((domain general-expressions) argument svar fvar)
(make-instance 'ge-ifourier :domain domain :argument argument
:space-var svar :freq-var fvar))
(defmethod print-object ((expr ge-ifourier) stream)
(format stream "IFour{~S, ~S->~S}"
(argument-of expr) (space-var-of expr) (freq-var-of expr)))