qlang 0.0.27180000 → 0.0.27182000

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,426 @@
1
+ from __future__ import division, print_function, absolute_import
2
+
3
+ __all__ = ['fixed_quad','quadrature','romberg','trapz','simps','romb',
4
+ 'cumtrapz','newton_cotes']
5
+
6
+ from scipy.special.orthogonal import p_roots
7
+ from scipy.special import gammaln
8
+ from numpy import sum, ones, add, diff, isinf, isscalar, \
9
+ asarray, real, trapz, arange, empty
10
+ import numpy as np
11
+ import math
12
+ import warnings
13
+
14
+ from scipy.lib.six import xrange
15
+
16
+
17
+ class AccuracyWarning(Warning):
18
+ pass
19
+
20
+
21
+ def _cached_p_roots(n):
22
+
23
+ if n in _cached_p_roots.cache:
24
+ return _cached_p_roots.cache[n]
25
+
26
+ _cached_p_roots.cache[n] = p_roots(n)
27
+ return _cached_p_roots.cache[n]
28
+ _cached_p_roots.cache = dict()
29
+
30
+
31
+ def fixed_quad(func,a,b,args=(),n=5):
32
+
33
+ [x,w] = _cached_p_roots(n)
34
+ x = real(x)
35
+ ainf, binf = map(isinf,(a,b))
36
+ if ainf or binf:
37
+ raise ValueError("Gaussian quadrature is only available for "
38
+ "finite limits.")
39
+ y = (b-a)*(x+1)/2.0 + a
40
+ return (b-a)/2.0*sum(w*func(y,*args),0), None
41
+
42
+
43
+ def vectorize1(func, args=(), vec_func=False):
44
+ if vec_func:
45
+ def vfunc(x):
46
+ return func(x, *args)
47
+ else:
48
+ def vfunc(x):
49
+ if isscalar(x):
50
+ return func(x, *args)
51
+ x = asarray(x)
52
+ # call with first point to get output type
53
+ y0 = func(x[0], *args)
54
+ n = len(x)
55
+ if hasattr(y0, 'dtype'):
56
+ output = empty((n,), dtype=y0.dtype)
57
+ else:
58
+ output = empty((n,), dtype=type(y0))
59
+ output[0] = y0
60
+ for i in xrange(1, n):
61
+ output[i] = func(x[i], *args)
62
+ return output
63
+ return vfunc
64
+
65
+
66
+ def quadrature(func, a, b, args=(), tol=1.49e-8, rtol=1.49e-8, maxiter=50,
67
+ vec_func=True, miniter=1):
68
+
69
+ if not isinstance(args, tuple):
70
+ args = (args,)
71
+ vfunc = vectorize1(func, args, vec_func=vec_func)
72
+ val = np.inf
73
+ err = np.inf
74
+ maxiter = max(miniter+1, maxiter)
75
+ for n in xrange(miniter, maxiter+1):
76
+ newval = fixed_quad(vfunc, a, b, (), n)[0]
77
+ err = abs(newval-val)
78
+ val = newval
79
+
80
+ if err < tol or err < rtol*abs(val):
81
+ break
82
+ else:
83
+ warnings.warn(
84
+ "maxiter (%d) exceeded. Latest difference = %e" % (maxiter, err),
85
+ AccuracyWarning)
86
+ return val, err
87
+
88
+
89
+ def tupleset(t, i, value):
90
+ l = list(t)
91
+ l[i] = value
92
+ return tuple(l)
93
+
94
+
95
+ def cumtrapz(y, x=None, dx=1.0, axis=-1, initial=None):
96
+ y = asarray(y)
97
+ if x is None:
98
+ d = dx
99
+ else:
100
+ x = asarray(x)
101
+ if x.ndim == 1:
102
+ d = diff(x)
103
+ # reshape to correct shape
104
+ shape = [1] * y.ndim
105
+ shape[axis] = -1
106
+ d = d.reshape(shape)
107
+ elif len(x.shape) != len(y.shape):
108
+ raise ValueError("If given, shape of x must be 1-d or the "
109
+ "same as y.")
110
+ else:
111
+ d = diff(x, axis=axis)
112
+
113
+ if d.shape[axis] != y.shape[axis] - 1:
114
+ raise ValueError("If given, length of x along axis must be the "
115
+ "same as y.")
116
+
117
+ nd = len(y.shape)
118
+ slice1 = tupleset((slice(None),)*nd, axis, slice(1, None))
119
+ slice2 = tupleset((slice(None),)*nd, axis, slice(None, -1))
120
+ res = add.accumulate(d * (y[slice1] + y[slice2]) / 2.0, axis)
121
+
122
+ if initial is not None:
123
+ if not np.isscalar(initial):
124
+ raise ValueError("`initial` parameter should be a scalar.")
125
+
126
+ shape = list(res.shape)
127
+ shape[axis] = 1
128
+ res = np.concatenate([np.ones(shape, dtype=res.dtype) * initial, res],
129
+ axis=axis)
130
+
131
+ return res
132
+
133
+
134
+ def _basic_simps(y,start,stop,x,dx,axis):
135
+ nd = len(y.shape)
136
+ if start is None:
137
+ start = 0
138
+ step = 2
139
+ all = (slice(None),)*nd
140
+ slice0 = tupleset(all, axis, slice(start, stop, step))
141
+ slice1 = tupleset(all, axis, slice(start+1, stop+1, step))
142
+ slice2 = tupleset(all, axis, slice(start+2, stop+2, step))
143
+
144
+ if x is None: # Even spaced Simpson's rule.
145
+ result = add.reduce(dx/3.0 * (y[slice0]+4*y[slice1]+y[slice2]),
146
+ axis)
147
+ else:
148
+ # Account for possibly different spacings.
149
+ # Simpson's rule changes a bit.
150
+ h = diff(x,axis=axis)
151
+ sl0 = tupleset(all, axis, slice(start, stop, step))
152
+ sl1 = tupleset(all, axis, slice(start+1, stop+1, step))
153
+ h0 = h[sl0]
154
+ h1 = h[sl1]
155
+ hsum = h0 + h1
156
+ hprod = h0 * h1
157
+ h0divh1 = h0 / h1
158
+ result = add.reduce(hsum/6.0*(y[slice0]*(2-1.0/h0divh1) +
159
+ y[slice1]*hsum*hsum/hprod +
160
+ y[slice2]*(2-h0divh1)),axis)
161
+ return result
162
+
163
+
164
+ def simps(y, x=None, dx=1, axis=-1, even='avg'):
165
+
166
+ y = asarray(y)
167
+ nd = len(y.shape)
168
+ N = y.shape[axis]
169
+ last_dx = dx
170
+ first_dx = dx
171
+ returnshape = 0
172
+ if x is not None:
173
+ x = asarray(x)
174
+ if len(x.shape) == 1:
175
+ shapex = ones(nd)
176
+ shapex[axis] = x.shape[0]
177
+ saveshape = x.shape
178
+ returnshape = 1
179
+ x = x.reshape(tuple(shapex))
180
+ elif len(x.shape) != len(y.shape):
181
+ raise ValueError("If given, shape of x must be 1-d or the "
182
+ "same as y.")
183
+ if x.shape[axis] != N:
184
+ raise ValueError("If given, length of x along axis must be the "
185
+ "same as y.")
186
+ if N % 2 == 0:
187
+ val = 0.0
188
+ result = 0.0
189
+ slice1 = (slice(None),)*nd
190
+ slice2 = (slice(None),)*nd
191
+ if even not in ['avg', 'last', 'first']:
192
+ raise ValueError("Parameter 'even' must be 'avg', 'last', or 'first'.")
193
+ # Compute using Simpson's rule on first intervals
194
+ if even in ['avg', 'first']:
195
+ slice1 = tupleset(slice1, axis, -1)
196
+ slice2 = tupleset(slice2, axis, -2)
197
+ if x is not None:
198
+ last_dx = x[slice1] - x[slice2]
199
+ val += 0.5*last_dx*(y[slice1]+y[slice2])
200
+ result = _basic_simps(y,0,N-3,x,dx,axis)
201
+ # Compute using Simpson's rule on last set of intervals
202
+ if even in ['avg', 'last']:
203
+ slice1 = tupleset(slice1, axis, 0)
204
+ slice2 = tupleset(slice2, axis, 1)
205
+ if x is not None:
206
+ first_dx = x[tuple(slice2)] - x[tuple(slice1)]
207
+ val += 0.5*first_dx*(y[slice2]+y[slice1])
208
+ result += _basic_simps(y,1,N-2,x,dx,axis)
209
+ if even == 'avg':
210
+ val /= 2.0
211
+ result /= 2.0
212
+ result = result + val
213
+ else:
214
+ result = _basic_simps(y,0,N-2,x,dx,axis)
215
+ if returnshape:
216
+ x = x.reshape(saveshape)
217
+ return result
218
+
219
+
220
+ def romb(y, dx=1.0, axis=-1, show=False):
221
+
222
+ y = asarray(y)
223
+ nd = len(y.shape)
224
+ Nsamps = y.shape[axis]
225
+ Ninterv = Nsamps-1
226
+ n = 1
227
+ k = 0
228
+ while n < Ninterv:
229
+ n <<= 1
230
+ k += 1
231
+ if n != Ninterv:
232
+ raise ValueError("Number of samples must be one plus a "
233
+ "non-negative power of 2.")
234
+
235
+ R = {}
236
+ all = (slice(None),) * nd
237
+ slice0 = tupleset(all, axis, 0)
238
+ slicem1 = tupleset(all, axis, -1)
239
+ h = Ninterv*asarray(dx)*1.0
240
+ R[(0,0)] = (y[slice0] + y[slicem1])/2.0*h
241
+ slice_R = all
242
+ start = stop = step = Ninterv
243
+ for i in range(1,k+1):
244
+ start >>= 1
245
+ slice_R = tupleset(slice_R, axis, slice(start,stop,step))
246
+ step >>= 1
247
+ R[(i,0)] = 0.5*(R[(i-1,0)] + h*add.reduce(y[slice_R],axis))
248
+ for j in range(1,i+1):
249
+ R[(i,j)] = R[(i,j-1)] + \
250
+ (R[(i,j-1)]-R[(i-1,j-1)]) / ((1 << (2*j))-1)
251
+ h = h / 2.0
252
+
253
+ if show:
254
+ if not isscalar(R[(0,0)]):
255
+ print("*** Printing table only supported for integrals" +
256
+ " of a single data set.")
257
+ else:
258
+ try:
259
+ precis = show[0]
260
+ except (TypeError, IndexError):
261
+ precis = 5
262
+ try:
263
+ width = show[1]
264
+ except (TypeError, IndexError):
265
+ width = 8
266
+ formstr = "%" + str(width) + '.' + str(precis)+'f'
267
+
268
+ print("\n Richardson Extrapolation Table for Romberg Integration ")
269
+ print("====================================================================")
270
+ for i in range(0,k+1):
271
+ for j in range(0,i+1):
272
+ print(formstr % R[(i,j)], end=' ')
273
+ print()
274
+ print("====================================================================\n")
275
+
276
+ return R[(k,k)]
277
+
278
+
279
+ def _difftrap(function, interval, numtraps):
280
+ if numtraps <= 0:
281
+ raise ValueError("numtraps must be > 0 in difftrap().")
282
+ elif numtraps == 1:
283
+ return 0.5*(function(interval[0])+function(interval[1]))
284
+ else:
285
+ numtosum = numtraps/2
286
+ h = float(interval[1]-interval[0])/numtosum
287
+ lox = interval[0] + 0.5 * h
288
+ points = lox + h * arange(0, numtosum)
289
+ s = sum(function(points),0)
290
+ return s
291
+
292
+
293
+ def _romberg_diff(b, c, k):
294
+
295
+ tmp = 4.0**k
296
+ return (tmp * c - b)/(tmp - 1.0)
297
+
298
+
299
+ def _printresmat(function, interval, resmat):
300
+ # Print the Romberg result matrix.
301
+ i = j = 0
302
+ print('Romberg integration of', repr(function), end=' ')
303
+ print('from', interval)
304
+ print('')
305
+ print('%6s %9s %9s' % ('Steps', 'StepSize', 'Results'))
306
+ for i in range(len(resmat)):
307
+ print('%6d %9f' % (2**i, (interval[1]-interval[0])/(2.**i)), end=' ')
308
+ for j in range(i+1):
309
+ print('%9f' % (resmat[i][j]), end=' ')
310
+ print('')
311
+ print('')
312
+ print('The final result is', resmat[i][j], end=' ')
313
+ print('after', 2**(len(resmat)-1)+1, 'function evaluations.')
314
+
315
+
316
+ def romberg(function, a, b, args=(), tol=1.48e-8, rtol=1.48e-8, show=False,
317
+ divmax=10, vec_func=False):
318
+ if isinf(a) or isinf(b):
319
+ raise ValueError("Romberg integration only available for finite limits.")
320
+ vfunc = vectorize1(function, args, vec_func=vec_func)
321
+ n = 1
322
+ interval = [a,b]
323
+ intrange = b-a
324
+ ordsum = _difftrap(vfunc, interval, n)
325
+ result = intrange * ordsum
326
+ resmat = [[result]]
327
+ err = np.inf
328
+ for i in xrange(1, divmax+1):
329
+ n = n * 2
330
+ ordsum = ordsum + _difftrap(vfunc, interval, n)
331
+ resmat.append([])
332
+ resmat[i].append(intrange * ordsum / n)
333
+ for k in range(i):
334
+ resmat[i].append(_romberg_diff(resmat[i-1][k], resmat[i][k], k+1))
335
+ result = resmat[i][i]
336
+ lastresult = resmat[i-1][i-1]
337
+
338
+ err = abs(result - lastresult)
339
+ if err < tol or err < rtol*abs(result):
340
+ break
341
+ else:
342
+ warnings.warn(
343
+ "divmax (%d) exceeded. Latest difference = %e" % (divmax, err),
344
+ AccuracyWarning)
345
+
346
+ if show:
347
+ _printresmat(vfunc, interval, resmat)
348
+ return result
349
+
350
+ _builtincoeffs = {
351
+ 1:(1,2,[1,1],-1,12),
352
+ 2:(1,3,[1,4,1],-1,90),
353
+ 3:(3,8,[1,3,3,1],-3,80),
354
+ 4:(2,45,[7,32,12,32,7],-8,945),
355
+ 5:(5,288,[19,75,50,50,75,19],-275,12096),
356
+ 6:(1,140,[41,216,27,272,27,216,41],-9,1400),
357
+ 7:(7,17280,[751,3577,1323,2989,2989,1323,3577,751],-8183,518400),
358
+ 8:(4,14175,[989,5888,-928,10496,-4540,10496,-928,5888,989],
359
+ -2368,467775),
360
+ 9:(9,89600,[2857,15741,1080,19344,5778,5778,19344,1080,
361
+ 15741,2857], -4671, 394240),
362
+ 10:(5,299376,[16067,106300,-48525,272400,-260550,427368,
363
+ -260550,272400,-48525,106300,16067],
364
+ -673175, 163459296),
365
+ 11:(11,87091200,[2171465,13486539,-3237113, 25226685,-9595542,
366
+ 15493566,15493566,-9595542,25226685,-3237113,
367
+ 13486539,2171465], -2224234463, 237758976000),
368
+ 12:(1, 5255250, [1364651,9903168,-7587864,35725120,-51491295,
369
+ 87516288,-87797136,87516288,-51491295,35725120,
370
+ -7587864,9903168,1364651], -3012, 875875),
371
+ 13:(13, 402361344000,[8181904909, 56280729661, -31268252574,
372
+ 156074417954,-151659573325,206683437987,
373
+ -43111992612,-43111992612,206683437987,
374
+ -151659573325,156074417954,-31268252574,
375
+ 56280729661,8181904909], -2639651053,
376
+ 344881152000),
377
+ 14:(7, 2501928000, [90241897,710986864,-770720657,3501442784,
378
+ -6625093363,12630121616,-16802270373,19534438464,
379
+ -16802270373,12630121616,-6625093363,3501442784,
380
+ -770720657,710986864,90241897], -3740727473,
381
+ 1275983280000)
382
+ }
383
+
384
+
385
+ def newton_cotes(rn, equal=0):
386
+ try:
387
+ N = len(rn)-1
388
+ if equal:
389
+ rn = np.arange(N+1)
390
+ elif np.all(np.diff(rn) == 1):
391
+ equal = 1
392
+ except:
393
+ N = rn
394
+ rn = np.arange(N+1)
395
+ equal = 1
396
+
397
+ if equal and N in _builtincoeffs:
398
+ na, da, vi, nb, db = _builtincoeffs[N]
399
+ return na*np.array(vi,float)/da, float(nb)/db
400
+
401
+ if (rn[0] != 0) or (rn[-1] != N):
402
+ raise ValueError("The sample positions must start at 0"
403
+ " and end at N")
404
+ yi = rn / float(N)
405
+ ti = 2.0*yi - 1
406
+ nvec = np.arange(0,N+1)
407
+ C = ti**nvec[:,np.newaxis]
408
+ Cinv = np.linalg.inv(C)
409
+ # improve precision of result
410
+ for i in range(2):
411
+ Cinv = 2*Cinv - Cinv.dot(C).dot(Cinv)
412
+ vec = 2.0 / (nvec[::2]+1)
413
+ ai = np.dot(Cinv[:,::2],vec) * N/2
414
+
415
+ if (N % 2 == 0) and equal:
416
+ BN = N/(N+3.)
417
+ power = N+2
418
+ else:
419
+ BN = N/(N+2.)
420
+ power = N+1
421
+
422
+ BN = BN - np.dot(yi**power, ai)
423
+ p1 = power+1
424
+ fac = power*math.log(N) - gammaln(p1)
425
+ fac = math.exp(fac)
426
+ return ai, BN*fac
@@ -0,0 +1,426 @@
1
+ from __future__ import division, print_function, absolute_import
2
+
3
+ __all__ = ['fixed_quad','quadrature','romberg','trapz','simps','romb',
4
+ 'cumtrapz','newton_cotes']
5
+
6
+ from scipy.special.orthogonal import p_roots
7
+ from scipy.special import gammaln
8
+ from numpy import sum, ones, add, diff, isinf, isscalar, \
9
+ asarray, real, trapz, arange, empty
10
+ import numpy as np
11
+ import math
12
+ import warnings
13
+
14
+ from scipy.lib.six import xrange
15
+
16
+
17
+ class AccuracyWarning(Warning):
18
+ pass
19
+
20
+
21
+ def _cached_p_roots(n):
22
+
23
+ if n in _cached_p_roots.cache:
24
+ return _cached_p_roots.cache[n]
25
+
26
+ _cached_p_roots.cache[n] = p_roots(n)
27
+ return _cached_p_roots.cache[n]
28
+ _cached_p_roots.cache = dict()
29
+
30
+
31
+ def fixed_quad(func,a,b,args=(),n=5):
32
+
33
+ [x,w] = _cached_p_roots(n)
34
+ x = real(x)
35
+ ainf, binf = map(isinf,(a,b))
36
+ if ainf or binf:
37
+ raise ValueError("Gaussian quadrature is only available for "
38
+ "finite limits.")
39
+ y = (b-a)*(x+1)/2.0 + a
40
+ return (b-a)/2.0*sum(w*func(y,*args),0), None
41
+
42
+
43
+ def vectorize1(func, args=(), vec_func=False):
44
+ if vec_func:
45
+ def vfunc(x):
46
+ return func(x, *args)
47
+ else:
48
+ def vfunc(x):
49
+ if isscalar(x):
50
+ return func(x, *args)
51
+ x = asarray(x)
52
+ # call with first point to get output type
53
+ y0 = func(x[0], *args)
54
+ n = len(x)
55
+ if hasattr(y0, 'dtype'):
56
+ output = empty((n,), dtype=y0.dtype)
57
+ else:
58
+ output = empty((n,), dtype=type(y0))
59
+ output[0] = y0
60
+ for i in xrange(1, n):
61
+ output[i] = func(x[i], *args)
62
+ return output
63
+ return vfunc
64
+
65
+
66
+ def quadrature(func, a, b, args=(), tol=1.49e-8, rtol=1.49e-8, maxiter=50,
67
+ vec_func=True, miniter=1):
68
+
69
+ if not isinstance(args, tuple):
70
+ args = (args,)
71
+ vfunc = vectorize1(func, args, vec_func=vec_func)
72
+ val = np.inf
73
+ err = np.inf
74
+ maxiter = max(miniter+1, maxiter)
75
+ for n in xrange(miniter, maxiter+1):
76
+ newval = fixed_quad(vfunc, a, b, (), n)[0]
77
+ err = abs(newval-val)
78
+ val = newval
79
+
80
+ if err < tol or err < rtol*abs(val):
81
+ break
82
+ else:
83
+ warnings.warn(
84
+ "maxiter (%d) exceeded. Latest difference = %e" % (maxiter, err),
85
+ AccuracyWarning)
86
+ return val, err
87
+
88
+
89
+ def tupleset(t, i, value):
90
+ l = list(t)
91
+ l[i] = value
92
+ return tuple(l)
93
+
94
+
95
+ def cumtrapz(y, x=None, dx=1.0, axis=-1, initial=None):
96
+ y = asarray(y)
97
+ if x is None:
98
+ d = dx
99
+ else:
100
+ x = asarray(x)
101
+ if x.ndim == 1:
102
+ d = diff(x)
103
+ # reshape to correct shape
104
+ shape = [1] * y.ndim
105
+ shape[axis] = -1
106
+ d = d.reshape(shape)
107
+ elif len(x.shape) != len(y.shape):
108
+ raise ValueError("If given, shape of x must be 1-d or the "
109
+ "same as y.")
110
+ else:
111
+ d = diff(x, axis=axis)
112
+
113
+ if d.shape[axis] != y.shape[axis] - 1:
114
+ raise ValueError("If given, length of x along axis must be the "
115
+ "same as y.")
116
+
117
+ nd = len(y.shape)
118
+ slice1 = tupleset((slice(None),)*nd, axis, slice(1, None))
119
+ slice2 = tupleset((slice(None),)*nd, axis, slice(None, -1))
120
+ res = add.accumulate(d * (y[slice1] + y[slice2]) / 2.0, axis)
121
+
122
+ if initial is not None:
123
+ if not np.isscalar(initial):
124
+ raise ValueError("`initial` parameter should be a scalar.")
125
+
126
+ shape = list(res.shape)
127
+ shape[axis] = 1
128
+ res = np.concatenate([np.ones(shape, dtype=res.dtype) * initial, res],
129
+ axis=axis)
130
+
131
+ return res
132
+
133
+
134
+ def _basic_simps(y,start,stop,x,dx,axis):
135
+ nd = len(y.shape)
136
+ if start is None:
137
+ start = 0
138
+ step = 2
139
+ all = (slice(None),)*nd
140
+ slice0 = tupleset(all, axis, slice(start, stop, step))
141
+ slice1 = tupleset(all, axis, slice(start+1, stop+1, step))
142
+ slice2 = tupleset(all, axis, slice(start+2, stop+2, step))
143
+
144
+ if x is None: # Even spaced Simpson's rule.
145
+ result = add.reduce(dx/3.0 * (y[slice0]+4*y[slice1]+y[slice2]),
146
+ axis)
147
+ else:
148
+ # Account for possibly different spacings.
149
+ # Simpson's rule changes a bit.
150
+ h = diff(x,axis=axis)
151
+ sl0 = tupleset(all, axis, slice(start, stop, step))
152
+ sl1 = tupleset(all, axis, slice(start+1, stop+1, step))
153
+ h0 = h[sl0]
154
+ h1 = h[sl1]
155
+ hsum = h0 + h1
156
+ hprod = h0 * h1
157
+ h0divh1 = h0 / h1
158
+ result = add.reduce(hsum/6.0*(y[slice0]*(2-1.0/h0divh1) +
159
+ y[slice1]*hsum*hsum/hprod +
160
+ y[slice2]*(2-h0divh1)),axis)
161
+ return result
162
+
163
+
164
+ def simps(y, x=None, dx=1, axis=-1, even='avg'):
165
+
166
+ y = asarray(y)
167
+ nd = len(y.shape)
168
+ N = y.shape[axis]
169
+ last_dx = dx
170
+ first_dx = dx
171
+ returnshape = 0
172
+ if x is not None:
173
+ x = asarray(x)
174
+ if len(x.shape) == 1:
175
+ shapex = ones(nd)
176
+ shapex[axis] = x.shape[0]
177
+ saveshape = x.shape
178
+ returnshape = 1
179
+ x = x.reshape(tuple(shapex))
180
+ elif len(x.shape) != len(y.shape):
181
+ raise ValueError("If given, shape of x must be 1-d or the "
182
+ "same as y.")
183
+ if x.shape[axis] != N:
184
+ raise ValueError("If given, length of x along axis must be the "
185
+ "same as y.")
186
+ if N % 2 == 0:
187
+ val = 0.0
188
+ result = 0.0
189
+ slice1 = (slice(None),)*nd
190
+ slice2 = (slice(None),)*nd
191
+ if even not in ['avg', 'last', 'first']:
192
+ raise ValueError("Parameter 'even' must be 'avg', 'last', or 'first'.")
193
+ # Compute using Simpson's rule on first intervals
194
+ if even in ['avg', 'first']:
195
+ slice1 = tupleset(slice1, axis, -1)
196
+ slice2 = tupleset(slice2, axis, -2)
197
+ if x is not None:
198
+ last_dx = x[slice1] - x[slice2]
199
+ val += 0.5*last_dx*(y[slice1]+y[slice2])
200
+ result = _basic_simps(y,0,N-3,x,dx,axis)
201
+ # Compute using Simpson's rule on last set of intervals
202
+ if even in ['avg', 'last']:
203
+ slice1 = tupleset(slice1, axis, 0)
204
+ slice2 = tupleset(slice2, axis, 1)
205
+ if x is not None:
206
+ first_dx = x[tuple(slice2)] - x[tuple(slice1)]
207
+ val += 0.5*first_dx*(y[slice2]+y[slice1])
208
+ result += _basic_simps(y,1,N-2,x,dx,axis)
209
+ if even == 'avg':
210
+ val /= 2.0
211
+ result /= 2.0
212
+ result = result + val
213
+ else:
214
+ result = _basic_simps(y,0,N-2,x,dx,axis)
215
+ if returnshape:
216
+ x = x.reshape(saveshape)
217
+ return result
218
+
219
+
220
+ def romb(y, dx=1.0, axis=-1, show=False):
221
+
222
+ y = asarray(y)
223
+ nd = len(y.shape)
224
+ Nsamps = y.shape[axis]
225
+ Ninterv = Nsamps-1
226
+ n = 1
227
+ k = 0
228
+ while n < Ninterv:
229
+ n <<= 1
230
+ k += 1
231
+ if n != Ninterv:
232
+ raise ValueError("Number of samples must be one plus a "
233
+ "non-negative power of 2.")
234
+
235
+ R = {}
236
+ all = (slice(None),) * nd
237
+ slice0 = tupleset(all, axis, 0)
238
+ slicem1 = tupleset(all, axis, -1)
239
+ h = Ninterv*asarray(dx)*1.0
240
+ R[(0,0)] = (y[slice0] + y[slicem1])/2.0*h
241
+ slice_R = all
242
+ start = stop = step = Ninterv
243
+ for i in range(1,k+1):
244
+ start >>= 1
245
+ slice_R = tupleset(slice_R, axis, slice(start,stop,step))
246
+ step >>= 1
247
+ R[(i,0)] = 0.5*(R[(i-1,0)] + h*add.reduce(y[slice_R],axis))
248
+ for j in range(1,i+1):
249
+ R[(i,j)] = R[(i,j-1)] + \
250
+ (R[(i,j-1)]-R[(i-1,j-1)]) / ((1 << (2*j))-1)
251
+ h = h / 2.0
252
+
253
+ if show:
254
+ if not isscalar(R[(0,0)]):
255
+ print("*** Printing table only supported for integrals" +
256
+ " of a single data set.")
257
+ else:
258
+ try:
259
+ precis = show[0]
260
+ except (TypeError, IndexError):
261
+ precis = 5
262
+ try:
263
+ width = show[1]
264
+ except (TypeError, IndexError):
265
+ width = 8
266
+ formstr = "%" + str(width) + '.' + str(precis)+'f'
267
+
268
+ print("\n Richardson Extrapolation Table for Romberg Integration ")
269
+ print("====================================================================")
270
+ for i in range(0,k+1):
271
+ for j in range(0,i+1):
272
+ print(formstr % R[(i,j)], end=' ')
273
+ print()
274
+ print("====================================================================\n")
275
+
276
+ return R[(k,k)]
277
+
278
+
279
+ def _difftrap(function, interval, numtraps):
280
+ if numtraps <= 0:
281
+ raise ValueError("numtraps must be > 0 in difftrap().")
282
+ elif numtraps == 1:
283
+ return 0.5*(function(interval[0])+function(interval[1]))
284
+ else:
285
+ numtosum = numtraps/2
286
+ h = float(interval[1]-interval[0])/numtosum
287
+ lox = interval[0] + 0.5 * h
288
+ points = lox + h * arange(0, numtosum)
289
+ s = sum(function(points),0)
290
+ return s
291
+
292
+
293
+ def _romberg_diff(b, c, k):
294
+
295
+ tmp = 4.0**k
296
+ return (tmp * c - b)/(tmp - 1.0)
297
+
298
+
299
+ def _printresmat(function, interval, resmat):
300
+ # Print the Romberg result matrix.
301
+ i = j = 0
302
+ print('Romberg integration of', repr(function), end=' ')
303
+ print('from', interval)
304
+ print('')
305
+ print('%6s %9s %9s' % ('Steps', 'StepSize', 'Results'))
306
+ for i in range(len(resmat)):
307
+ print('%6d %9f' % (2**i, (interval[1]-interval[0])/(2.**i)), end=' ')
308
+ for j in range(i+1):
309
+ print('%9f' % (resmat[i][j]), end=' ')
310
+ print('')
311
+ print('')
312
+ print('The final result is', resmat[i][j], end=' ')
313
+ print('after', 2**(len(resmat)-1)+1, 'function evaluations.')
314
+
315
+
316
+ def romberg(function, a, b, args=(), tol=1.48e-8, rtol=1.48e-8, show=False,
317
+ divmax=10, vec_func=False):
318
+ if isinf(a) or isinf(b):
319
+ raise ValueError("Romberg integration only available for finite limits.")
320
+ vfunc = vectorize1(function, args, vec_func=vec_func)
321
+ n = 1
322
+ interval = [a,b]
323
+ intrange = b-a
324
+ ordsum = _difftrap(vfunc, interval, n)
325
+ result = intrange * ordsum
326
+ resmat = [[result]]
327
+ err = np.inf
328
+ for i in xrange(1, divmax+1):
329
+ n = n * 2
330
+ ordsum = ordsum + _difftrap(vfunc, interval, n)
331
+ resmat.append([])
332
+ resmat[i].append(intrange * ordsum / n)
333
+ for k in range(i):
334
+ resmat[i].append(_romberg_diff(resmat[i-1][k], resmat[i][k], k+1))
335
+ result = resmat[i][i]
336
+ lastresult = resmat[i-1][i-1]
337
+
338
+ err = abs(result - lastresult)
339
+ if err < tol or err < rtol*abs(result):
340
+ break
341
+ else:
342
+ warnings.warn(
343
+ "divmax (%d) exceeded. Latest difference = %e" % (divmax, err),
344
+ AccuracyWarning)
345
+
346
+ if show:
347
+ _printresmat(vfunc, interval, resmat)
348
+ return result
349
+
350
+ _builtincoeffs = {
351
+ 1:(1,2,[1,1],-1,12),
352
+ 2:(1,3,[1,4,1],-1,90),
353
+ 3:(3,8,[1,3,3,1],-3,80),
354
+ 4:(2,45,[7,32,12,32,7],-8,945),
355
+ 5:(5,288,[19,75,50,50,75,19],-275,12096),
356
+ 6:(1,140,[41,216,27,272,27,216,41],-9,1400),
357
+ 7:(7,17280,[751,3577,1323,2989,2989,1323,3577,751],-8183,518400),
358
+ 8:(4,14175,[989,5888,-928,10496,-4540,10496,-928,5888,989],
359
+ -2368,467775),
360
+ 9:(9,89600,[2857,15741,1080,19344,5778,5778,19344,1080,
361
+ 15741,2857], -4671, 394240),
362
+ 10:(5,299376,[16067,106300,-48525,272400,-260550,427368,
363
+ -260550,272400,-48525,106300,16067],
364
+ -673175, 163459296),
365
+ 11:(11,87091200,[2171465,13486539,-3237113, 25226685,-9595542,
366
+ 15493566,15493566,-9595542,25226685,-3237113,
367
+ 13486539,2171465], -2224234463, 237758976000),
368
+ 12:(1, 5255250, [1364651,9903168,-7587864,35725120,-51491295,
369
+ 87516288,-87797136,87516288,-51491295,35725120,
370
+ -7587864,9903168,1364651], -3012, 875875),
371
+ 13:(13, 402361344000,[8181904909, 56280729661, -31268252574,
372
+ 156074417954,-151659573325,206683437987,
373
+ -43111992612,-43111992612,206683437987,
374
+ -151659573325,156074417954,-31268252574,
375
+ 56280729661,8181904909], -2639651053,
376
+ 344881152000),
377
+ 14:(7, 2501928000, [90241897,710986864,-770720657,3501442784,
378
+ -6625093363,12630121616,-16802270373,19534438464,
379
+ -16802270373,12630121616,-6625093363,3501442784,
380
+ -770720657,710986864,90241897], -3740727473,
381
+ 1275983280000)
382
+ }
383
+
384
+
385
+ def newton_cotes(rn, equal=0):
386
+ try:
387
+ N = len(rn)-1
388
+ if equal:
389
+ rn = np.arange(N+1)
390
+ elif np.all(np.diff(rn) == 1):
391
+ equal = 1
392
+ except:
393
+ N = rn
394
+ rn = np.arange(N+1)
395
+ equal = 1
396
+
397
+ if equal and N in _builtincoeffs:
398
+ na, da, vi, nb, db = _builtincoeffs[N]
399
+ return na*np.array(vi,float)/da, float(nb)/db
400
+
401
+ if (rn[0] != 0) or (rn[-1] != N):
402
+ raise ValueError("The sample positions must start at 0"
403
+ " and end at N")
404
+ yi = rn / float(N)
405
+ ti = 2.0*yi - 1
406
+ nvec = np.arange(0,N+1)
407
+ C = ti**nvec[:,np.newaxis]
408
+ Cinv = np.linalg.inv(C)
409
+ # improve precision of result
410
+ for i in range(2):
411
+ Cinv = 2*Cinv - Cinv.dot(C).dot(Cinv)
412
+ vec = 2.0 / (nvec[::2]+1)
413
+ ai = np.dot(Cinv[:,::2],vec) * N/2
414
+
415
+ if (N % 2 == 0) and equal:
416
+ BN = N/(N+3.)
417
+ power = N+2
418
+ else:
419
+ BN = N/(N+2.)
420
+ power = N+1
421
+
422
+ BN = BN - np.dot(yi**power, ai)
423
+ p1 = power+1
424
+ fac = power*math.log(N) - gammaln(p1)
425
+ fac = math.exp(fac)
426
+ return ai, BN*fac