@@ -70,7 +70,7 @@ def numerical_integral(func, a, b=None,
70
70
algorithm = ' qag' ,
71
71
max_points = 87 , params = [], eps_abs = 1e-6 ,
72
72
eps_rel = 1e-6 , rule = 6 ):
73
- r """
73
+ r """
74
74
Return the numerical integral of the function on the interval
75
75
from a to b and an error bound.
76
76
@@ -241,40 +241,52 @@ def numerical_integral(func, a, b=None,
241
241
Traceback ( most recent call last) :
242
242
...
243
243
TypeError: unable to simplify to float approximation
244
- """
245
244
246
- cdef double abs_err # step size
247
- cdef double result
248
- cdef int i
249
- cdef int j
250
- cdef double _a, _b
251
- cdef PyFunctionWrapper wrapper # struct to pass information into GSL C function
245
+ Check for :trac:`15496`::
252
246
253
- if b is None or isinstance (a, (list , tuple )):
254
- b = a[1 ]
255
- a = a[0 ]
247
+ sage: f = x^ 2/exp( -1/( x^ 2+ 1)) /( x^ 2+ 1)
248
+ sage: D = integrate( f,( x,-infinity,infinity) ,hold=True)
249
+ sage: D. n( )
250
+ Traceback ( most recent call last) :
251
+ ...
252
+ ValueError: integral does not converge at -infinity
253
+ """
254
+ cdef double abs_err # step size
255
+ cdef double result
256
+ cdef int i
257
+ cdef int j
258
+ cdef double _a, _b
259
+ cdef PyFunctionWrapper wrapper # struct to pass information into GSL C function
260
+
261
+ if b is None or isinstance (a, (list , tuple )):
262
+ b = a[1 ]
263
+ a = a[0 ]
256
264
257
- # The integral over a point is always zero
258
- if a == b:
259
- return (0.0 , 0.0 )
265
+ # The integral over a point is always zero
266
+ if a == b:
267
+ return (0.0 , 0.0 )
260
268
261
- if not callable (func):
269
+ if not callable (func):
262
270
# handle the constant case
263
271
return (((< double > b - < double > a) * < double > func), 0.0 )
264
272
265
- cdef gsl_function F
266
- cdef gsl_integration_workspace* W
267
- W = NULL
273
+ cdef gsl_function F
274
+ cdef gsl_integration_workspace* W
275
+ W = NULL
268
276
269
- if not isinstance (func, FastDoubleFunc):
277
+ if not isinstance (func, FastDoubleFunc):
278
+ from sage.rings.infinity import Infinity
270
279
try :
271
280
if hasattr (func, ' arguments' ):
272
281
vars = func.arguments()
273
282
else :
274
283
vars = func.variables()
275
- if len (vars ) == 0 :
276
- # handle the constant case
277
- return (((< double > b - < double > a) * < double > func), 0.0 )
284
+ except (AttributeError ):
285
+ pass
286
+ else :
287
+ if not vars :
288
+ # handle the constant case
289
+ return (((< double > b - < double > a) * < double > func), 0.0 )
278
290
if len (vars ) != 1 :
279
291
if len (params) + 1 != len (vars ):
280
292
raise ValueError ((" The function to be integrated depends on "
@@ -285,70 +297,85 @@ def numerical_integral(func, a, b=None,
285
297
286
298
to_sub = dict (zip (vars [1 :], params))
287
299
func = func.subs(to_sub)
288
- func = func._fast_float_(str (vars [0 ]))
289
- except (AttributeError ):
290
- pass
291
300
292
- if isinstance (func, FastDoubleFunc):
301
+ # sanity checks for integration up to infinity
302
+ v = str (vars [0 ])
303
+ if a is - Infinity:
304
+ try :
305
+ ell = func.limit(** {v: - Infinity})
306
+ except (AttributeError , ValueError ):
307
+ pass
308
+ else :
309
+ if ell.is_numeric() and not ell.is_zero():
310
+ raise ValueError (' integral does not converge at -infinity' )
311
+ if b is Infinity:
312
+ try :
313
+ ell = func.limit(** {v: Infinity})
314
+ except (AttributeError , ValueError ):
315
+ pass
316
+ else :
317
+ if ell.is_numeric() and not ell.is_zero():
318
+ raise ValueError (' integral does not converge at infinity' )
319
+ func = func._fast_float_(v)
320
+
321
+ if isinstance (func, FastDoubleFunc):
293
322
F.function = c_ff
294
323
F.params = < void * > func
295
324
296
- elif not isinstance (func, compiled_integrand):
325
+ elif not isinstance (func, compiled_integrand):
297
326
wrapper = PyFunctionWrapper()
298
327
if not func is None :
299
328
wrapper.the_function = func
300
329
else :
301
330
raise ValueError (" No integrand defined" )
302
331
try :
303
- if params == [] and len (sage_getargspec(wrapper.the_function)[0 ]) == 1 :
304
- wrapper.the_parameters= []
305
- elif params == [] and len (sage_getargspec(wrapper.the_function)[0 ]) > 1 :
332
+ if not params and len (sage_getargspec(wrapper.the_function)[0 ]) == 1 :
333
+ wrapper.the_parameters = []
334
+ elif not params and len (sage_getargspec(wrapper.the_function)[0 ]) > 1 :
306
335
raise ValueError (" Integrand has parameters but no parameters specified" )
307
- elif params! = [] :
336
+ elif params:
308
337
wrapper.the_parameters = params
309
338
except TypeError :
310
- wrapper.the_function = eval (" lambda x: func(x)" , {' func' :func})
339
+ wrapper.the_function = eval (" lambda x: func(x)" , {' func' : func})
311
340
wrapper.the_parameters = []
312
341
313
342
F.function = c_f
314
343
F.params = < void * > wrapper
315
344
345
+ cdef size_t n
346
+ n = max_points
316
347
317
- cdef size_t n
318
- n = max_points
348
+ gsl_set_error_handler_off()
319
349
320
- gsl_set_error_handler_off()
321
-
322
- if algorithm == " qng" :
350
+ if algorithm == " qng" :
323
351
_a= a
324
352
_b= b
325
353
sig_on()
326
354
gsl_integration_qng(& F, _a, _b, eps_abs, eps_rel, & result, & abs_err, & n)
327
355
sig_off()
328
356
329
- elif algorithm == " qag" :
330
- from sage.rings.infinity import Infinity
331
- if a is - Infinity and b is + Infinity:
357
+ elif algorithm == " qag" :
358
+ if a is - Infinity and b is + Infinity:
332
359
W = < gsl_integration_workspace* > gsl_integration_workspace_alloc(n)
333
360
sig_on()
334
361
gsl_integration_qagi(& F, eps_abs, eps_rel, n, W, & result, & abs_err)
335
362
sig_off()
336
363
337
- elif a is - Infinity:
364
+ elif a is - Infinity:
338
365
_b = b
339
366
W = < gsl_integration_workspace* > gsl_integration_workspace_alloc(n)
340
367
sig_on()
341
368
gsl_integration_qagil(& F, _b, eps_abs, eps_rel, n, W, & result, & abs_err)
342
369
sig_off()
343
370
344
- elif b is + Infinity:
371
+ elif b is + Infinity:
345
372
_a = a
346
373
W = < gsl_integration_workspace* > gsl_integration_workspace_alloc(n)
347
374
sig_on()
348
375
gsl_integration_qagiu(& F, _a, eps_abs, eps_rel, n, W, & result, & abs_err)
349
376
sig_off()
350
377
351
- else :
378
+ else :
352
379
_a = a
353
380
_b = b
354
381
W = < gsl_integration_workspace* > gsl_integration_workspace_alloc(n)
@@ -357,7 +384,7 @@ def numerical_integral(func, a, b=None,
357
384
sig_off()
358
385
359
386
360
- elif algorithm == " qags" :
387
+ elif algorithm == " qags" :
361
388
362
389
W = < gsl_integration_workspace* > gsl_integration_workspace_alloc(n)
363
390
sig_on()
@@ -366,13 +393,14 @@ def numerical_integral(func, a, b=None,
366
393
gsl_integration_qags(& F, _a, _b, eps_abs, eps_rel, n, W, & result, & abs_err)
367
394
sig_off()
368
395
369
- else :
396
+ else :
370
397
raise TypeError (" invalid integration algorithm" )
371
398
372
- if W != NULL :
399
+ if W != NULL :
373
400
gsl_integration_workspace_free(W)
374
401
375
- return result, abs_err
402
+ return result, abs_err
403
+
376
404
377
405
cdef double c_monte_carlo_f(double * t, size_t dim, void * params):
378
406
cdef double value
@@ -393,6 +421,7 @@ cdef double c_monte_carlo_f(double *t, size_t dim, void *params):
393
421
394
422
return value
395
423
424
+
396
425
cdef double c_monte_carlo_ff(double * x, size_t dim, void * params):
397
426
cdef double result
398
427
(< Wrapper_rdf> params).call_c(x, & result)
@@ -598,11 +627,11 @@ def monte_carlo_integral(func, xl, xu, size_t calls, algorithm='plain',
598
627
wrapper = PyFunctionWrapper()
599
628
wrapper.the_function = func
600
629
601
- if params == [] and len (sage_getargspec(wrapper.the_function)[0 ]) == dim:
630
+ if not params and len (sage_getargspec(wrapper.the_function)[0 ]) == dim:
602
631
wrapper.the_parameters = []
603
- elif params == [] and len (sage_getargspec(wrapper.the_function)[0 ]) > dim:
632
+ elif not params and len (sage_getargspec(wrapper.the_function)[0 ]) > dim:
604
633
raise ValueError (" Integrand has parameters but no parameters specified" )
605
- elif params ! = [] :
634
+ elif params:
606
635
wrapper.the_parameters = params
607
636
wrapper.lx = [None ] * dim
608
637
0 commit comments