from scipy._lib._array_api import array_namespace, np_compat from functools import cached_property from scipy.special import roots_legendre from ._base import FixedRule class GaussLegendreQuadrature(FixedRule): """ Gauss-Legendre quadrature. Parameters ---------- npoints : int Number of nodes for the higher-order rule. xp : array_namespace, optional The namespace for the node and weight arrays. Default is None, where NumPy is used. Examples -------- Evaluate a 1D integral. Note in this example that ``f`` returns an array, so the estimates will also be arrays. >>> import numpy as np >>> from scipy.integrate import cubature >>> from scipy.integrate._rules import GaussLegendreQuadrature >>> def f(x): ... return np.cos(x) >>> rule = GaussLegendreQuadrature(21) # Use 21-point GaussLegendre >>> a, b = np.array([0]), np.array([1]) >>> rule.estimate(f, a, b) # True value sin(1), approximately 0.84147 array([0.84147098]) >>> rule.estimate_error(f, a, b) array([1.11022302e-16]) """ def __init__(self, npoints, xp=None): if npoints < 2: raise ValueError( "At least 2 nodes required for Gauss-Legendre cubature" ) self.npoints = npoints if xp is None: xp = np_compat self.xp = array_namespace(xp.empty(0)) @cached_property def nodes_and_weights(self): # TODO: current converting to/from numpy nodes, weights = roots_legendre(self.npoints) return ( self.xp.asarray(nodes, dtype=self.xp.float64), self.xp.asarray(weights, dtype=self.xp.float64) )