Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/calculus/interpolators.pyx
4056 views
1
"""
2
Complex Interpolation
3
4
AUTHORS:
5
6
- Ethan Van Andel (2009): initial version
7
8
Development supported by NSF award No. 0702939.
9
"""
10
11
#*****************************************************************************
12
# Copyright (C) 2009 Ethan Van Andel <[email protected]>,
13
#
14
# Distributed under the terms of the GNU General Public License (GPL)
15
#
16
# This code is distributed in the hope that it will be useful,
17
# but WITHOUT ANY WARRANTY; without even the implied warranty of
18
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
# General Public License for more details.
20
#
21
# The full text of the GPL is available at:
22
#
23
# http://www.gnu.org/licenses/
24
#*****************************************************************************
25
26
import numpy as np
27
cimport numpy as np
28
29
from math import pi
30
cdef double TWOPI = 2*pi
31
32
def polygon_spline(pts):
33
"""
34
Creates a polygon from a set of complex or `(x,y)` points. The polygon
35
will be a parametric curve from 0 to 2*pi. The returned values will be
36
complex, not `(x,y)`.
37
38
INPUT:
39
40
- ``pts`` -- A list or array of complex numbers of tuples of the form
41
`(x,y)`.
42
43
EXAMPLES:
44
45
A simple square::
46
47
sage: pts = [(-1, -1), (1, -1), (1, 1), (-1, 1)]
48
sage: ps = polygon_spline(pts)
49
sage: fx = lambda x: ps.value(x).real
50
sage: fy = lambda x: ps.value(x).imag
51
sage: show(parametric_plot((fx, fy), (0, 2*pi)))
52
sage: m = Riemann_Map([lambda x: ps.value(real(x))], [lambda x: ps.derivative(real(x))],0)
53
sage: show(m.plot_colored() + m.plot_spiderweb())
54
55
Polygon approximation of an circle::
56
57
sage: pts = [e^(I*t / 25) for t in xrange(25)]
58
sage: ps = polygon_spline(pts)
59
sage: ps.derivative(2)
60
(-0.0470303661...+0.1520363883...j)
61
"""
62
return PSpline(pts)
63
64
cdef class PSpline:
65
"""
66
A ``CCSpline`` object contains a polygon interpolation of a figure
67
in the complex plane.
68
69
EXAMPLES:
70
71
A simple ``square``::
72
73
sage: pts = [(-1, -1), (1, -1), (1, 1), (-1, 1)]
74
sage: ps = polygon_spline(pts)
75
sage: ps.value(0)
76
(-1-1j)
77
sage: ps.derivative(0)
78
(1.27323954...+0j)
79
"""
80
cdef int N
81
cdef np.ndarray pts
82
83
def __init__(self, pts):
84
"""
85
TESTS::
86
87
sage: pts = [(-1, -1), (1, -1), (1, 1), (-1, 1)]
88
sage: ps = polygon_spline(pts)
89
"""
90
if type(pts[0]) == type((0,0)):
91
self.pts = np.array(
92
[np.complex(i[0], i[1]) for i in pts], dtype=np.complex128)
93
else:
94
self.pts = np.array(pts, dtype=np.complex128)
95
self.N = len(pts)
96
97
def value(self, double t):
98
"""
99
Returns the derivative (speed and direction of the curve) of a
100
given point from the parameter ``t``.
101
102
INPUT:
103
104
- ``t`` -- double, the parameter value for the parameterized curve,
105
between 0 and 2*pi.
106
107
OUTPUT:
108
109
A complex number representing the point on the polygon corresponding
110
to the input ``t``.
111
112
EXAMPLES:
113
114
::
115
116
sage: pts = [(-1, -1), (1, -1), (1, 1), (-1, 1)]
117
sage: ps = polygon_spline(pts)
118
sage: ps.value(.5)
119
(-0.363380227632...-1j)
120
sage: ps.value(0) - ps.value(2*pi)
121
0j
122
sage: ps.value(10)
123
(0.26760455264...+1j)
124
"""
125
cdef double t1 = ((t / TWOPI*self.N) % self.N)
126
pt1 = self.pts[int(t1)]
127
pt2 = self.pts[(int(t1) + 1) % self.N]
128
return pt1 + (pt2 - pt1) * (t1 - int(t1))
129
130
def derivative(self, double t):
131
"""
132
Returns the derivative (speed and direction of the curve) of a
133
given point from the parameter ``t``.
134
135
INPUT:
136
137
- ``t`` -- double, the parameter value for the parameterized curve,
138
between 0 and 2*pi.
139
140
OUTPUT:
141
142
A complex number representing the derivative at the point on the
143
polygon corresponding to the input ``t``.
144
145
EXAMPLES:
146
147
::
148
149
sage: pts = [(-1, -1), (1, -1), (1, 1), (-1, 1)]
150
sage: ps = polygon_spline(pts)
151
sage: ps.derivative(1 / 3)
152
(1.27323954473...+0j)
153
sage: ps.derivative(0) - ps.derivative(2*pi)
154
0j
155
sage: ps.derivative(10)
156
(-1.27323954473...+0j)
157
"""
158
cdef double t1 = ((t / TWOPI*self.N) % self.N)
159
pt1 = self.pts[int(t1)]
160
pt2 = self.pts[(int(t1) + 1) % self.N]
161
return (pt2 - pt1) * self.N / TWOPI
162
163
def complex_cubic_spline(pts):
164
"""
165
Creates a cubic spline interpolated figure from a set of complex or
166
`(x,y)` points. The figure will be a parametric curve from 0 to 2*pi.
167
The returned values will be complex, not `(x,y)`.
168
169
INPUT:
170
171
- ``pts`` A list or array of complex numbers, or tuples of the form
172
`(x,y)`.
173
174
EXAMPLES:
175
176
A simple ``square``::
177
178
sage: pts = [(-1, -1), (1, -1), (1, 1), (-1, 1)]
179
sage: cs = complex_cubic_spline(pts)
180
sage: fx = lambda x: cs.value(x).real
181
sage: fy = lambda x: cs.value(x).imag
182
sage: show(parametric_plot((fx, fy), (0, 2*pi)))
183
sage: m = Riemann_Map([lambda x: cs.value(real(x))], [lambda x: cs.derivative(real(x))], 0)
184
sage: show(m.plot_colored() + m.plot_spiderweb())
185
186
Polygon approximation of a circle::
187
188
sage: pts = [e^(I*t / 25) for t in xrange(25)]
189
sage: cs = complex_cubic_spline(pts)
190
sage: cs.derivative(2)
191
(-0.0497765406583...+0.151095006434...j)
192
"""
193
return CCSpline(pts)
194
195
cdef class CCSpline:
196
"""
197
A ``CCSpline`` object contains a cubic interpolation of a figure
198
in the complex plane.
199
200
EXAMPLES:
201
202
A simple ``square``::
203
204
sage: pts = [(-1, -1), (1, -1), (1, 1), (-1, 1)]
205
sage: cs = complex_cubic_spline(pts)
206
sage: cs.value(0)
207
(-1-1j)
208
sage: cs.derivative(0)
209
(0.9549296...-0.9549296...j)
210
"""
211
cdef int N
212
cdef np.ndarray avec,bvec,cvec,dvec
213
214
#standard cubic interpolation method
215
def __init__(self, pts):
216
"""
217
TESTS::
218
219
sage: pts = [(-1, -1), (1, -1), (1, 1), (-1, 1)]
220
sage: cs = complex_cubic_spline(pts)
221
"""
222
if type(pts[0]) == type((0,0)):
223
pts = np.array(
224
[np.complex(pt[0], pt[1]) for pt in pts], dtype=np.complex128)
225
cdef int N, i, k
226
N = len(pts)
227
yvec = np.zeros(N, dtype=np.complex128)
228
for i in xrange(N):
229
yvec[i] = 3 * (pts[(i - 1) % N] - 2*pts[i] + pts[(i + 1) % N])
230
bmat = np.zeros([N, N], dtype=np.complex128)
231
for i in xrange(N):
232
bmat[i, i] = 4
233
bmat[(i - 1) % N, i] = 1
234
bmat[(i + 1) % N, i] = 1
235
bvec = (np.linalg.solve(bmat, yvec))
236
cvec = np.zeros(N, dtype=np.complex128)
237
for i in xrange(N):
238
cvec[i] = (pts[(i + 1) % N] - pts[i] - 1.0/3.0 *
239
bvec[(i + 1) % N] - 2./3. * bvec[i])
240
dvec = np.array(pts, dtype=np.complex128)
241
avec = np.zeros(N, dtype=np.complex128)
242
for i in xrange(N):
243
avec[i] = 1.0/3.0 * (bvec[(i + 1) % N] - bvec[i])
244
self.avec = avec
245
self.bvec = bvec
246
self.cvec = cvec
247
self.dvec = dvec
248
self.N = N
249
250
def value(self, double t):
251
"""
252
Returns the location of a given point from the parameter ``t``.
253
254
INPUT:
255
256
- ``t`` -- double, the parameter value for the parameterized curve,
257
between 0 and 2*pi.
258
259
OUTPUT:
260
261
A complex number representing the point on the figure corresponding
262
to the input ``t``.
263
264
EXAMPLES:
265
266
::
267
268
sage: pts = [(-1, -1), (1, -1), (1, 1), (-1, 1)]
269
sage: cs = complex_cubic_spline(pts)
270
sage: cs.value(4 / 7)
271
(-0.303961332787...-1.34716728183...j)
272
sage: cs.value(0) - cs.value(2*pi)
273
0j
274
sage: cs.value(-2.73452)
275
(0.934561222231...+0.881366116402...j)
276
"""
277
cdef double t1 = (t / TWOPI * self.N) % self.N
278
cdef int j = int(t1)
279
return (self.avec[j] * (t1 - j)**3 + self.bvec[j] * (t1 - j)**2 +
280
self.cvec[j] * (t1 - j) + self.dvec[j])
281
282
def derivative(self, double t):
283
"""
284
Returns the derivative (speed and direction of the curve) of a
285
given point from the parameter ``t``.
286
287
INPUT:
288
289
- ``t`` -- double, the parameter value for the parameterized curve,
290
between 0 and 2*pi.
291
292
OUTPUT:
293
294
A complex number representing the derivative at the point on the
295
figure corresponding to the input ``t``.
296
297
EXAMPLES:
298
299
::
300
301
sage: pts = [(-1, -1), (1, -1), (1, 1), (-1, 1)]
302
sage: cs = complex_cubic_spline(pts)
303
sage: cs.derivative(3 / 5)
304
(1.40578892327...-0.225417136326...j)
305
sage: cs.derivative(0) - cs.derivative(2 * pi)
306
0j
307
sage: cs.derivative(-6)
308
(2.52047692949...-1.89392588310...j)
309
"""
310
cdef double t1 = (t / TWOPI * self.N) % self.N
311
cdef int j = int(t1)
312
return (3 * self.avec[j] * (t1 - j)**2 + 2 * self.bvec[j] * (t1 - j) +
313
self.cvec[j]) / TWOPI * self.N
314
315