@@ -70,7 +70,7 @@ def numerical_integral(func, a, b=None,
7070 algorithm = ' qag' ,
7171 max_points = 87 , params = [], eps_abs = 1e-6 ,
7272 eps_rel = 1e-6 , rule = 6 ):
73- r """
73+ r """
7474 Return the numerical integral of the function on the interval
7575 from a to b and an error bound.
7676
@@ -241,40 +241,52 @@ def numerical_integral(func, a, b=None,
241241 Traceback ( most recent call last) :
242242 ...
243243 TypeError: unable to simplify to float approximation
244- """
245244
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`::
252246
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 ]
256264
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 )
260268
261- if not callable (func):
269+ if not callable (func):
262270 # handle the constant case
263271 return (((< double > b - < double > a) * < double > func), 0.0 )
264272
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
268276
269- if not isinstance (func, FastDoubleFunc):
277+ if not isinstance (func, FastDoubleFunc):
278+ from sage.rings.infinity import Infinity
270279 try :
271280 if hasattr (func, ' arguments' ):
272281 vars = func.arguments()
273282 else :
274283 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 )
278290 if len (vars ) != 1 :
279291 if len (params) + 1 != len (vars ):
280292 raise ValueError ((" The function to be integrated depends on "
@@ -285,70 +297,85 @@ def numerical_integral(func, a, b=None,
285297
286298 to_sub = dict (zip (vars [1 :], params))
287299 func = func.subs(to_sub)
288- func = func._fast_float_(str (vars [0 ]))
289- except (AttributeError ):
290- pass
291300
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):
293322 F.function = c_ff
294323 F.params = < void * > func
295324
296- elif not isinstance (func, compiled_integrand):
325+ elif not isinstance (func, compiled_integrand):
297326 wrapper = PyFunctionWrapper()
298327 if not func is None :
299328 wrapper.the_function = func
300329 else :
301330 raise ValueError (" No integrand defined" )
302331 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 :
306335 raise ValueError (" Integrand has parameters but no parameters specified" )
307- elif params! = [] :
336+ elif params:
308337 wrapper.the_parameters = params
309338 except TypeError :
310- wrapper.the_function = eval (" lambda x: func(x)" , {' func' :func})
339+ wrapper.the_function = eval (" lambda x: func(x)" , {' func' : func})
311340 wrapper.the_parameters = []
312341
313342 F.function = c_f
314343 F.params = < void * > wrapper
315344
345+ cdef size_t n
346+ n = max_points
316347
317- cdef size_t n
318- n = max_points
348+ gsl_set_error_handler_off()
319349
320- gsl_set_error_handler_off()
321-
322- if algorithm == " qng" :
350+ if algorithm == " qng" :
323351 _a= a
324352 _b= b
325353 sig_on()
326354 gsl_integration_qng(& F, _a, _b, eps_abs, eps_rel, & result, & abs_err, & n)
327355 sig_off()
328356
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:
332359 W = < gsl_integration_workspace* > gsl_integration_workspace_alloc(n)
333360 sig_on()
334361 gsl_integration_qagi(& F, eps_abs, eps_rel, n, W, & result, & abs_err)
335362 sig_off()
336363
337- elif a is - Infinity:
364+ elif a is - Infinity:
338365 _b = b
339366 W = < gsl_integration_workspace* > gsl_integration_workspace_alloc(n)
340367 sig_on()
341368 gsl_integration_qagil(& F, _b, eps_abs, eps_rel, n, W, & result, & abs_err)
342369 sig_off()
343370
344- elif b is + Infinity:
371+ elif b is + Infinity:
345372 _a = a
346373 W = < gsl_integration_workspace* > gsl_integration_workspace_alloc(n)
347374 sig_on()
348375 gsl_integration_qagiu(& F, _a, eps_abs, eps_rel, n, W, & result, & abs_err)
349376 sig_off()
350377
351- else :
378+ else :
352379 _a = a
353380 _b = b
354381 W = < gsl_integration_workspace* > gsl_integration_workspace_alloc(n)
@@ -357,7 +384,7 @@ def numerical_integral(func, a, b=None,
357384 sig_off()
358385
359386
360- elif algorithm == " qags" :
387+ elif algorithm == " qags" :
361388
362389 W = < gsl_integration_workspace* > gsl_integration_workspace_alloc(n)
363390 sig_on()
@@ -366,13 +393,14 @@ def numerical_integral(func, a, b=None,
366393 gsl_integration_qags(& F, _a, _b, eps_abs, eps_rel, n, W, & result, & abs_err)
367394 sig_off()
368395
369- else :
396+ else :
370397 raise TypeError (" invalid integration algorithm" )
371398
372- if W != NULL :
399+ if W != NULL :
373400 gsl_integration_workspace_free(W)
374401
375- return result, abs_err
402+ return result, abs_err
403+
376404
377405cdef double c_monte_carlo_f(double * t, size_t dim, void * params):
378406 cdef double value
@@ -393,6 +421,7 @@ cdef double c_monte_carlo_f(double *t, size_t dim, void *params):
393421
394422 return value
395423
424+
396425cdef double c_monte_carlo_ff(double * x, size_t dim, void * params):
397426 cdef double result
398427 (< Wrapper_rdf> params).call_c(x, & result)
@@ -598,11 +627,11 @@ def monte_carlo_integral(func, xl, xu, size_t calls, algorithm='plain',
598627 wrapper = PyFunctionWrapper()
599628 wrapper.the_function = func
600629
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:
602631 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:
604633 raise ValueError (" Integrand has parameters but no parameters specified" )
605- elif params ! = [] :
634+ elif params:
606635 wrapper.the_parameters = params
607636 wrapper.lx = [None ] * dim
608637
0 commit comments