comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/polynomial/polyutils.py @ 87:2a2c65a20a8b

Add Python libs and headers
author Chris Cannam
date Wed, 25 Feb 2015 14:05:22 +0000
parents
children
comparison
equal deleted inserted replaced
86:413a9d26189e 87:2a2c65a20a8b
1 """
2 Utililty classes and functions for the polynomial modules.
3
4 This module provides: error and warning objects; a polynomial base class;
5 and some routines used in both the `polynomial` and `chebyshev` modules.
6
7 Error objects
8 -------------
9
10 .. autosummary::
11 :toctree: generated/
12
13 PolyError base class for this sub-package's errors.
14 PolyDomainError raised when domains are mismatched.
15
16 Warning objects
17 ---------------
18
19 .. autosummary::
20 :toctree: generated/
21
22 RankWarning raised in least-squares fit for rank-deficient matrix.
23
24 Base class
25 ----------
26
27 .. autosummary::
28 :toctree: generated/
29
30 PolyBase Obsolete base class for the polynomial classes. Do not use.
31
32 Functions
33 ---------
34
35 .. autosummary::
36 :toctree: generated/
37
38 as_series convert list of array_likes into 1-D arrays of common type.
39 trimseq remove trailing zeros.
40 trimcoef remove small trailing coefficients.
41 getdomain return the domain appropriate for a given set of abscissae.
42 mapdomain maps points between domains.
43 mapparms parameters of the linear map between domains.
44
45 """
46 from __future__ import division, absolute_import, print_function
47
48 import numpy as np
49
50 __all__ = [
51 'RankWarning', 'PolyError', 'PolyDomainError', 'as_series', 'trimseq',
52 'trimcoef', 'getdomain', 'mapdomain', 'mapparms', 'PolyBase']
53
54 #
55 # Warnings and Exceptions
56 #
57
58 class RankWarning(UserWarning):
59 """Issued by chebfit when the design matrix is rank deficient."""
60 pass
61
62 class PolyError(Exception):
63 """Base class for errors in this module."""
64 pass
65
66 class PolyDomainError(PolyError):
67 """Issued by the generic Poly class when two domains don't match.
68
69 This is raised when an binary operation is passed Poly objects with
70 different domains.
71
72 """
73 pass
74
75 #
76 # Base class for all polynomial types
77 #
78
79 class PolyBase(object):
80 """
81 Base class for all polynomial types.
82
83 Deprecated in numpy 1.9.0, use the abstract
84 ABCPolyBase class instead. Note that the latter
85 reguires a number of virtual functions to be
86 implemented.
87
88 """
89 pass
90
91 #
92 # Helper functions to convert inputs to 1-D arrays
93 #
94 def trimseq(seq):
95 """Remove small Poly series coefficients.
96
97 Parameters
98 ----------
99 seq : sequence
100 Sequence of Poly series coefficients. This routine fails for
101 empty sequences.
102
103 Returns
104 -------
105 series : sequence
106 Subsequence with trailing zeros removed. If the resulting sequence
107 would be empty, return the first element. The returned sequence may
108 or may not be a view.
109
110 Notes
111 -----
112 Do not lose the type info if the sequence contains unknown objects.
113
114 """
115 if len(seq) == 0:
116 return seq
117 else:
118 for i in range(len(seq) - 1, -1, -1):
119 if seq[i] != 0:
120 break
121 return seq[:i+1]
122
123
124 def as_series(alist, trim=True):
125 """
126 Return argument as a list of 1-d arrays.
127
128 The returned list contains array(s) of dtype double, complex double, or
129 object. A 1-d argument of shape ``(N,)`` is parsed into ``N`` arrays of
130 size one; a 2-d argument of shape ``(M,N)`` is parsed into ``M`` arrays
131 of size ``N`` (i.e., is "parsed by row"); and a higher dimensional array
132 raises a Value Error if it is not first reshaped into either a 1-d or 2-d
133 array.
134
135 Parameters
136 ----------
137 a : array_like
138 A 1- or 2-d array_like
139 trim : boolean, optional
140 When True, trailing zeros are removed from the inputs.
141 When False, the inputs are passed through intact.
142
143 Returns
144 -------
145 [a1, a2,...] : list of 1-D arrays
146 A copy of the input data as a list of 1-d arrays.
147
148 Raises
149 ------
150 ValueError
151 Raised when `as_series` cannot convert its input to 1-d arrays, or at
152 least one of the resulting arrays is empty.
153
154 Examples
155 --------
156 >>> from numpy import polynomial as P
157 >>> a = np.arange(4)
158 >>> P.as_series(a)
159 [array([ 0.]), array([ 1.]), array([ 2.]), array([ 3.])]
160 >>> b = np.arange(6).reshape((2,3))
161 >>> P.as_series(b)
162 [array([ 0., 1., 2.]), array([ 3., 4., 5.])]
163
164 """
165 arrays = [np.array(a, ndmin=1, copy=0) for a in alist]
166 if min([a.size for a in arrays]) == 0:
167 raise ValueError("Coefficient array is empty")
168 if any([a.ndim != 1 for a in arrays]):
169 raise ValueError("Coefficient array is not 1-d")
170 if trim:
171 arrays = [trimseq(a) for a in arrays]
172
173 if any([a.dtype == np.dtype(object) for a in arrays]):
174 ret = []
175 for a in arrays:
176 if a.dtype != np.dtype(object):
177 tmp = np.empty(len(a), dtype=np.dtype(object))
178 tmp[:] = a[:]
179 ret.append(tmp)
180 else:
181 ret.append(a.copy())
182 else:
183 try:
184 dtype = np.common_type(*arrays)
185 except:
186 raise ValueError("Coefficient arrays have no common type")
187 ret = [np.array(a, copy=1, dtype=dtype) for a in arrays]
188 return ret
189
190
191 def trimcoef(c, tol=0):
192 """
193 Remove "small" "trailing" coefficients from a polynomial.
194
195 "Small" means "small in absolute value" and is controlled by the
196 parameter `tol`; "trailing" means highest order coefficient(s), e.g., in
197 ``[0, 1, 1, 0, 0]`` (which represents ``0 + x + x**2 + 0*x**3 + 0*x**4``)
198 both the 3-rd and 4-th order coefficients would be "trimmed."
199
200 Parameters
201 ----------
202 c : array_like
203 1-d array of coefficients, ordered from lowest order to highest.
204 tol : number, optional
205 Trailing (i.e., highest order) elements with absolute value less
206 than or equal to `tol` (default value is zero) are removed.
207
208 Returns
209 -------
210 trimmed : ndarray
211 1-d array with trailing zeros removed. If the resulting series
212 would be empty, a series containing a single zero is returned.
213
214 Raises
215 ------
216 ValueError
217 If `tol` < 0
218
219 See Also
220 --------
221 trimseq
222
223 Examples
224 --------
225 >>> from numpy import polynomial as P
226 >>> P.trimcoef((0,0,3,0,5,0,0))
227 array([ 0., 0., 3., 0., 5.])
228 >>> P.trimcoef((0,0,1e-3,0,1e-5,0,0),1e-3) # item == tol is trimmed
229 array([ 0.])
230 >>> i = complex(0,1) # works for complex
231 >>> P.trimcoef((3e-4,1e-3*(1-i),5e-4,2e-5*(1+i)), 1e-3)
232 array([ 0.0003+0.j , 0.0010-0.001j])
233
234 """
235 if tol < 0:
236 raise ValueError("tol must be non-negative")
237
238 [c] = as_series([c])
239 [ind] = np.where(np.abs(c) > tol)
240 if len(ind) == 0:
241 return c[:1]*0
242 else:
243 return c[:ind[-1] + 1].copy()
244
245 def getdomain(x):
246 """
247 Return a domain suitable for given abscissae.
248
249 Find a domain suitable for a polynomial or Chebyshev series
250 defined at the values supplied.
251
252 Parameters
253 ----------
254 x : array_like
255 1-d array of abscissae whose domain will be determined.
256
257 Returns
258 -------
259 domain : ndarray
260 1-d array containing two values. If the inputs are complex, then
261 the two returned points are the lower left and upper right corners
262 of the smallest rectangle (aligned with the axes) in the complex
263 plane containing the points `x`. If the inputs are real, then the
264 two points are the ends of the smallest interval containing the
265 points `x`.
266
267 See Also
268 --------
269 mapparms, mapdomain
270
271 Examples
272 --------
273 >>> from numpy.polynomial import polyutils as pu
274 >>> points = np.arange(4)**2 - 5; points
275 array([-5, -4, -1, 4])
276 >>> pu.getdomain(points)
277 array([-5., 4.])
278 >>> c = np.exp(complex(0,1)*np.pi*np.arange(12)/6) # unit circle
279 >>> pu.getdomain(c)
280 array([-1.-1.j, 1.+1.j])
281
282 """
283 [x] = as_series([x], trim=False)
284 if x.dtype.char in np.typecodes['Complex']:
285 rmin, rmax = x.real.min(), x.real.max()
286 imin, imax = x.imag.min(), x.imag.max()
287 return np.array((complex(rmin, imin), complex(rmax, imax)))
288 else:
289 return np.array((x.min(), x.max()))
290
291 def mapparms(old, new):
292 """
293 Linear map parameters between domains.
294
295 Return the parameters of the linear map ``offset + scale*x`` that maps
296 `old` to `new` such that ``old[i] -> new[i]``, ``i = 0, 1``.
297
298 Parameters
299 ----------
300 old, new : array_like
301 Domains. Each domain must (successfully) convert to a 1-d array
302 containing precisely two values.
303
304 Returns
305 -------
306 offset, scale : scalars
307 The map ``L(x) = offset + scale*x`` maps the first domain to the
308 second.
309
310 See Also
311 --------
312 getdomain, mapdomain
313
314 Notes
315 -----
316 Also works for complex numbers, and thus can be used to calculate the
317 parameters required to map any line in the complex plane to any other
318 line therein.
319
320 Examples
321 --------
322 >>> from numpy import polynomial as P
323 >>> P.mapparms((-1,1),(-1,1))
324 (0.0, 1.0)
325 >>> P.mapparms((1,-1),(-1,1))
326 (0.0, -1.0)
327 >>> i = complex(0,1)
328 >>> P.mapparms((-i,-1),(1,i))
329 ((1+1j), (1+0j))
330
331 """
332 oldlen = old[1] - old[0]
333 newlen = new[1] - new[0]
334 off = (old[1]*new[0] - old[0]*new[1])/oldlen
335 scl = newlen/oldlen
336 return off, scl
337
338 def mapdomain(x, old, new):
339 """
340 Apply linear map to input points.
341
342 The linear map ``offset + scale*x`` that maps the domain `old` to
343 the domain `new` is applied to the points `x`.
344
345 Parameters
346 ----------
347 x : array_like
348 Points to be mapped. If `x` is a subtype of ndarray the subtype
349 will be preserved.
350 old, new : array_like
351 The two domains that determine the map. Each must (successfully)
352 convert to 1-d arrays containing precisely two values.
353
354 Returns
355 -------
356 x_out : ndarray
357 Array of points of the same shape as `x`, after application of the
358 linear map between the two domains.
359
360 See Also
361 --------
362 getdomain, mapparms
363
364 Notes
365 -----
366 Effectively, this implements:
367
368 .. math ::
369 x\\_out = new[0] + m(x - old[0])
370
371 where
372
373 .. math ::
374 m = \\frac{new[1]-new[0]}{old[1]-old[0]}
375
376 Examples
377 --------
378 >>> from numpy import polynomial as P
379 >>> old_domain = (-1,1)
380 >>> new_domain = (0,2*np.pi)
381 >>> x = np.linspace(-1,1,6); x
382 array([-1. , -0.6, -0.2, 0.2, 0.6, 1. ])
383 >>> x_out = P.mapdomain(x, old_domain, new_domain); x_out
384 array([ 0. , 1.25663706, 2.51327412, 3.76991118, 5.02654825,
385 6.28318531])
386 >>> x - P.mapdomain(x_out, new_domain, old_domain)
387 array([ 0., 0., 0., 0., 0., 0.])
388
389 Also works for complex numbers (and thus can be used to map any line in
390 the complex plane to any other line therein).
391
392 >>> i = complex(0,1)
393 >>> old = (-1 - i, 1 + i)
394 >>> new = (-1 + i, 1 - i)
395 >>> z = np.linspace(old[0], old[1], 6); z
396 array([-1.0-1.j , -0.6-0.6j, -0.2-0.2j, 0.2+0.2j, 0.6+0.6j, 1.0+1.j ])
397 >>> new_z = P.mapdomain(z, old, new); new_z
398 array([-1.0+1.j , -0.6+0.6j, -0.2+0.2j, 0.2-0.2j, 0.6-0.6j, 1.0-1.j ])
399
400 """
401 x = np.asanyarray(x)
402 off, scl = mapparms(old, new)
403 return off + scl*x