+
    Y°³jF  ã                   óŽ   € ^ RI HtHt ^ RIHt  ! R R4      t ! R R]4      t ! R R]4      t ! R	 R
]4      tR t	RR lt
R tR# )é    )Úarray_namespaceÚxp_size)Úcached_propertyc                   ó8   a € ] tR t^t o RtRR ltRR ltRtV tR# )ÚRulea²  
Base class for numerical integration algorithms (cubatures).

Finds an estimate for the integral of ``f`` over the region described by two arrays
``a`` and ``b`` via `estimate`, and find an estimate for the error of this
approximation via `estimate_error`.

If a subclass does not implement its own `estimate_error`, then it will use a
default error estimate based on the difference between the estimate over the whole
region and the sum of estimates over that region divided into ``2^ndim`` subregions.

See Also
--------
FixedRule

Examples
--------
In the following, a custom rule is created which uses 3D Genz-Malik cubature for
the estimate of the integral, and the difference between this estimate and a less
accurate estimate using 5-node Gauss-Legendre quadrature as an estimate for the
error.

>>> import numpy as np
>>> from scipy.integrate import cubature
>>> from scipy.integrate._rules import (
...     Rule, ProductNestedFixed, GenzMalikCubature, GaussLegendreQuadrature
... )
>>> def f(x, r, alphas):
...     # f(x) = cos(2*pi*r + alpha @ x)
...     # Need to allow r and alphas to be arbitrary shape
...     npoints, ndim = x.shape[0], x.shape[-1]
...     alphas_reshaped = alphas[np.newaxis, :]
...     x_reshaped = x.reshape(npoints, *([1]*(len(alphas.shape) - 1)), ndim)
...     return np.cos(2*np.pi*r + np.sum(alphas_reshaped * x_reshaped, axis=-1))
>>> genz = GenzMalikCubature(ndim=3)
>>> gauss = GaussKronrodQuadrature(npoints=21)
>>> # Gauss-Kronrod is 1D, so we find the 3D product rule:
>>> gauss_3d = ProductNestedFixed([gauss, gauss, gauss])
>>> class CustomRule(Rule):
...     def estimate(self, f, a, b, args=()):
...         return genz.estimate(f, a, b, args)
...     def estimate_error(self, f, a, b, args=()):
...         return np.abs(
...             genz.estimate(f, a, b, args)
...             - gauss_3d.estimate(f, a, b, args)
...         )
>>> rng = np.random.default_rng()
>>> res = cubature(
...     f=f,
...     a=np.array([0, 0, 0]),
...     b=np.array([1, 1, 1]),
...     rule=CustomRule(),
...     args=(rng.random((2,)), rng.random((3, 2, 3)))
... )
>>> res.estimate
 array([[-0.95179502,  0.12444608],
        [-0.96247411,  0.60866385],
        [-0.97360014,  0.25515587]])
c                ó   € \         h)aÛ  
Calculate estimate of integral of `f` in rectangular region described by
corners `a` and ``b``.

Parameters
----------
f : callable
    Function to integrate. `f` must have the signature::
        f(x : ndarray, \*args) -> ndarray

    `f` should accept arrays ``x`` of shape::
        (npoints, ndim)

    and output arrays of shape::
        (npoints, output_dim_1, ..., output_dim_n)

    In this case, `estimate` will return arrays of shape::
        (output_dim_1, ..., output_dim_n)
a, b : ndarray
    Lower and upper limits of integration as rank-1 arrays specifying the left
    and right endpoints of the intervals being integrated over. Infinite limits
    are currently not supported.
args : tuple, optional
    Additional positional args passed to ``f``, if any.

Returns
-------
est : ndarray
    Result of estimation. If `f` returns arrays of shape ``(npoints,
    output_dim_1, ..., output_dim_n)``, then `est` will be of shape
    ``(output_dim_1, ..., output_dim_n)``.
©ÚNotImplementedError)ÚselfÚfÚaÚbÚargss   &&&&&Ú]/home/luca/screen-checking/.venv/lib/python3.14/site-packages/scipy/integrate/_rules/_base.pyÚestimateÚRule.estimateC   s   € ôB "Ð!ó    c                óÄ   € V P                  WW44      p^ p\        W#4       F  w  rxW`P                  WW„4      ,          pK  	  V P                  P                  WV,
          4      # )a  
Estimate the error of the approximation for the integral of `f` in rectangular
region described by corners `a` and `b`.

If a subclass does not override this method, then a default error estimator is
used. This estimates the error as ``|est - refined_est|`` where ``est`` is
``estimate(f, a, b)`` and ``refined_est`` is the sum of
``estimate(f, a_k, b_k)`` where ``a_k, b_k`` are the coordinates of each
subregion of the region described by ``a`` and ``b``. In the 1D case, this
is equivalent to comparing the integral over an entire interval ``[a, b]`` to
the sum of the integrals over the left and right subintervals, ``[a, (a+b)/2]``
and ``[(a+b)/2, b]``.

Parameters
----------
f : callable
    Function to estimate error for. `f` must have the signature::
        f(x : ndarray, \*args) -> ndarray

    `f` should accept arrays `x` of shape::
        (npoints, ndim)

    and output arrays of shape::
        (npoints, output_dim_1, ..., output_dim_n)

    In this case, `estimate` will return arrays of shape::
        (output_dim_1, ..., output_dim_n)
a, b : ndarray
    Lower and upper limits of integration as rank-1 arrays specifying the left
    and right endpoints of the intervals being integrated over. Infinite limits
    are currently not supported.
args : tuple, optional
    Additional positional args passed to `f`, if any.

Returns
-------
err_est : ndarray
    Result of error estimation. If `f` returns arrays of shape
    ``(npoints, output_dim_1, ..., output_dim_n)``, then `est` will be
    of shape ``(output_dim_1, ..., output_dim_n)``.
)r   Ú_split_subregionÚxpÚabs)	r   r   r   r   r   ÚestÚrefined_estÚa_kÚb_ks	   &&&&&    r   Úestimate_errorÚRule.estimate_errorf   sV   € ðV �m‰m˜A !Ó*ˆØˆä(¨Ö.‰HˆCØŸ=™=¨°Ó;Õ;ŠKñ /ð �w‰w�{‰{˜3Õ,Ó-Ð-r   © N©r   )	Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   r   Ú__static_attributes__Ú__classdictcell__©Ú__classdict__s   @r   r   r      s   ø‡ € ñ:ôx!"÷F1.ò 1.r   r   c                   óD   a € ] tR t^št o RtR t]R 4       tRR ltRt	V t
R# )Ú	FixedRulea^  
A rule implemented as the weighted sum of function evaluations at fixed nodes.

Attributes
----------
nodes_and_weights : (ndarray, ndarray)
    A tuple ``(nodes, weights)`` of nodes at which to evaluate ``f`` and the
    corresponding weights. ``nodes`` should be of shape ``(num_nodes,)`` for 1D
    cubature rules (quadratures) and more generally for N-D cubature rules, it
    should be of shape ``(num_nodes, ndim)``. ``weights`` should be of shape
    ``(num_nodes,)``. The nodes and weights should be for integrals over
    :math:`[-1, 1]^n`.

See Also
--------
GaussLegendreQuadrature, GaussKronrodQuadrature, GenzMalikCubature

Examples
--------

Implementing Simpson's 1/3 rule:

>>> import numpy as np
>>> from scipy.integrate._rules import FixedRule
>>> class SimpsonsQuad(FixedRule):
...     @property
...     def nodes_and_weights(self):
...         nodes = np.array([-1, 0, 1])
...         weights = np.array([1/3, 4/3, 1/3])
...         return (nodes, weights)
>>> rule = SimpsonsQuad()
>>> rule.estimate(
...     f=lambda x: x**2,
...     a=np.array([0]),
...     b=np.array([1]),
... )
 [0.3333333]
c                ó   € R V n         R # ©N©r   ©r   s   &r   Ú__init__ÚFixedRule.__init__Â   s	   € ØˆŽr   c                ó   € \         hr,   r	   r.   s   &r   Únodes_and_weightsÚFixedRule.nodes_and_weightsÅ   s   € ä!Ð!r   c           	     óŠ   € V P                   w  rVV P                  f   \        V4      V n        \        WW5WdV P                  4      # )am  
Calculate estimate of integral of `f` in rectangular region described by
corners `a` and `b` as ``sum(weights * f(nodes))``.

Nodes and weights will automatically be adjusted from calculating integrals over
:math:`[-1, 1]^n` to :math:`[a, b]^n`.

Parameters
----------
f : callable
    Function to integrate. `f` must have the signature::
        f(x : ndarray, \*args) -> ndarray

    `f` should accept arrays `x` of shape::
        (npoints, ndim)

    and output arrays of shape::
        (npoints, output_dim_1, ..., output_dim_n)

    In this case, `estimate` will return arrays of shape::
        (output_dim_1, ..., output_dim_n)
a, b : ndarray
    Lower and upper limits of integration as rank-1 arrays specifying the left
    and right endpoints of the intervals being integrated over. Infinite limits
    are currently not supported.
args : tuple, optional
    Additional positional args passed to `f`, if any.

Returns
-------
est : ndarray
    Result of estimation. If `f` returns arrays of shape ``(npoints,
    output_dim_1, ..., output_dim_n)``, then `est` will be of shape
    ``(output_dim_1, ..., output_dim_n)``.
)r2   r   r   Ú_apply_fixed_rule)r   r   r   r   r   ÚnodesÚweightss   &&&&&  r   r   ÚFixedRule.estimateÉ   s<   € ðH ×/Ñ/‰ˆà�7‰7Š?Ü% eÓ,ˆDŒGä   q°ÀÇÁÓHÐHr   r-   Nr   )r    r!   r"   r#   r$   r/   Úpropertyr2   r   r%   r&   r'   s   @r   r*   r*   š   s0   ø‡ € ñ%òNð ñ"ó ð"÷)Iò )Ir   r*   c                   óT   a € ] tR t^õt o RtR t]R 4       t]R 4       tRR lt	Rt
V tR# )	ÚNestedFixedRuleab  
A cubature rule with error estimate given by the difference between two underlying
fixed rules.

If constructed as ``NestedFixedRule(higher, lower)``, this will use::

    estimate(f, a, b) := higher.estimate(f, a, b)
    estimate_error(f, a, b) := \|higher.estimate(f, a, b) - lower.estimate(f, a, b)|

(where the absolute value is taken elementwise).

Attributes
----------
higher : Rule
    Higher accuracy rule.

lower : Rule
    Lower accuracy rule.

See Also
--------
GaussKronrodQuadrature

Examples
--------

>>> from scipy.integrate import cubature
>>> from scipy.integrate._rules import (
...     GaussLegendreQuadrature, NestedFixedRule, ProductNestedFixed
... )
>>> higher = GaussLegendreQuadrature(10)
>>> lower = GaussLegendreQuadrature(5)
>>> rule = NestedFixedRule(
...     higher,
...     lower
... )
>>> rule_2d = ProductNestedFixed([rule, rule])
c                ó,   € Wn         W n        R V n        R # r,   ©ÚhigherÚlowerr   )r   r>   r?   s   &&&r   r/   ÚNestedFixedRule.__init__  s   € ØŒØŒ
ØˆŽr   c                óV   € V P                   e   V P                   P                  # \        hr,   )r>   r2   r
   r.   s   &r   r2   Ú!NestedFixedRule.nodes_and_weights"  s"   € à�;‰;Ò"Ø—;‘;×0Ñ0Ð0ä%Ð%r   c                óV   € V P                   e   V P                   P                  # \        hr,   )r?   r2   r
   r.   s   &r   Úlower_nodes_and_weightsÚ'NestedFixedRule.lower_nodes_and_weights)  s"   € à�:‰:Ò!Ø—:‘:×/Ñ/Ð/ä%Ð%r   c                óR  € V P                   w  rVV P                  w  rxV P                  f   \        V4      V n        V P                  P	                  WW.^ R7      p	V P                  P	                  Wh) .^ R7      p
V P                  P                  \        WW9W¤V P                  4      4      # )a  
Estimate the error of the approximation for the integral of `f` in rectangular
region described by corners `a` and `b`.

Parameters
----------
f : callable
    Function to estimate error for. `f` must have the signature::
        f(x : ndarray, \*args) -> ndarray

    `f` should accept arrays `x` of shape::
        (npoints, ndim)

    and output arrays of shape::
        (npoints, output_dim_1, ..., output_dim_n)

    In this case, `estimate` will return arrays of shape::
        (output_dim_1, ..., output_dim_n)
a, b : ndarray
    Lower and upper limits of integration as rank-1 arrays specifying the left
    and right endpoints of the intervals being integrated over. Infinite limits
    are currently not supported.
args : tuple, optional
    Additional positional args passed to `f`, if any.

Returns
-------
err_est : ndarray
    Result of error estimation. If `f` returns arrays of shape
    ``(npoints, output_dim_1, ..., output_dim_n)``, then `est` will be
    of shape ``(output_dim_1, ..., output_dim_n)``.
©Úaxis)r2   rD   r   r   Úconcatr   r5   )r   r   r   r   r   r6   r7   Úlower_nodesÚlower_weightsÚerror_nodesÚerror_weightss   &&&&&      r   r   ÚNestedFixedRule.estimate_error0  s�   € ðD ×/Ñ/‰ˆØ%)×%AÑ%AÑ"ˆà�7‰7Š?Ü% eÓ,ˆDŒGà—g‘g—n‘n eÐ%9À�nÓBˆØŸ™Ÿ™¨°Ð'@Àq˜ÓIˆà�w‰w�{‰{Ü˜a A°MÈÏÉÓQó
ð 	
r   r=   Nr   )r    r!   r"   r#   r$   r/   r9   r2   rD   r   r%   r&   r'   s   @r   r;   r;   õ   sB   ø‡ € ñ%òNð
 ñ&ó ð&ð ñ&ó ð&÷-
ò -
r   r;   c                   óJ   a € ] tR tRt o RtR t]R 4       t]R 4       tRt	V t
R# )ÚProductNestedFixedi`  aÔ  
Find the n-dimensional cubature rule constructed from the Cartesian product of 1-D
`NestedFixedRule` quadrature rules.

Given a list of N 1-dimensional quadrature rules which support error estimation
using NestedFixedRule, this will find the N-dimensional cubature rule obtained by
taking the Cartesian product of their nodes, and estimating the error by taking the
difference with a lower-accuracy N-dimensional cubature rule obtained using the
``.lower_nodes_and_weights`` rule in each of the base 1-dimensional rules.

Parameters
----------
base_rules : list of NestedFixedRule
    List of base 1-dimensional `NestedFixedRule` quadrature rules.

Attributes
----------
base_rules : list of NestedFixedRule
    List of base 1-dimensional `NestedFixedRule` qudarature rules.

Examples
--------

Evaluate a 2D integral by taking the product of two 1D rules:

>>> import numpy as np
>>> from scipy.integrate import cubature
>>> from scipy.integrate._rules import (
...  ProductNestedFixed, GaussKronrodQuadrature
... )
>>> def f(x):
...     # f(x) = cos(x_1) + cos(x_2)
...     return np.sum(np.cos(x), axis=-1)
>>> rule = ProductNestedFixed(
...     [GaussKronrodQuadrature(15), GaussKronrodQuadrature(15)]
... ) # Use 15-point Gauss-Kronrod, which implements NestedFixedRule
>>> a, b = np.array([0, 0]), np.array([1, 1])
>>> rule.estimate(f, a, b) # True value 2*sin(1), approximately 1.6829
 np.float64(1.682941969615793)
>>> rule.estimate_error(f, a, b)
 np.float64(2.220446049250313e-16)
c                ót   € V F$  p\        V\        4      '       d   K  \        R 4      h	  Wn        RV n        R# )z<base rules for product need to be instance ofNestedFixedRuleN)Ú
isinstancer;   Ú
ValueErrorÚ
base_rulesr   )r   rT   Úrules   && r   r/   ÚProductNestedFixed.__init__Œ  s9   € ÛˆDÜ˜d¤O×4Ô4Ü ð "3ó 4ð 4ñ ð
 %ŒØˆŽr   c           	     ób  € \        V P                   Uu. uF  qP                  ^ ,          NK  	  up4      pV P                  f   \	        V4      V n        V P                  P                  \        V P                   Uu. uF  qP                  ^,          NK  	  up4      RR7      pW#3# u upi u upi ©r   rG   éÿÿÿÿ)Ú_cartesian_productrT   r2   r   r   Úprod)r   rU   r6   r7   s   &   r   r2   Ú$ProductNestedFixed.nodes_and_weights•  s¡   € ä"Ø37·?²?ÓC±?¨4×#Ñ# A×&Ð&±?ÑCó
ˆð �7‰7Š?Ü% eÓ,ˆDŒGà—'‘'—,‘,ÜØ7;·²ÓG±¨t×'Ñ'¨×*Ð*±ÑGóð ð	 ó 
ˆð ˆ~Ðùò Dùò Hó   ”B'Á<B,c           	     ób  € \        V P                   Uu. uF  qP                  ^ ,          NK  	  up4      pV P                  f   \	        V4      V n        V P                  P                  \        V P                   Uu. uF  qP                  ^,          NK  	  up4      RR7      pW#3# u upi u upi rX   )rZ   rT   rD   r   r   r[   )r   Úcubaturer6   r7   s   &   r   rD   Ú*ProductNestedFixed.lower_nodes_and_weights§  s¡   € ä"ØAEÇÂÓQÁ°X×-Ñ-¨a×0Ð0ÁÑQó
ˆð �7‰7Š?Ü% eÓ,ˆDŒGà—'‘'—,‘,ÜØEIÇ_Â_ÓUÁ_¸×1Ñ1°!×4Ð4Á_ÑUóð ð	 ó 
ˆð ˆ~Ðùò Rùò Vr]   )rT   r   N)r    r!   r"   r#   r$   r/   r   r2   rD   r%   r&   r'   s   @r   rP   rP   `  s8   ø‡ € ñ)òVð ñó ðð" ñó ör   rP   c                 ó˜   € \        V !  pVP                  ! V R R/ pVP                  VP                  VRR7      R\	        V 4      34      pV# )ÚindexingÚijrG   rY   )r   ÚmeshgridÚreshapeÚstackÚlen)Úarraysr   Ú	arrays_ixÚresults   &   r   rZ   rZ   º  sJ   € Ü	˜&Ñ	!€Bà—’˜VÐ3¨dÑ3€IØ�Z‰Z˜Ÿ™ °˜Ó4°r¼3¸v»;Ð6GÓH€Fà€Mr   Nc              #  ó  "  € \        W4      pVf   W,           ^,          p\        V P                  ^ ,          4       Uu. uF!  qBP                  W,          W4,          34      NK#  	  pp\        VP                  ^ ,          4       Uu. uF!  qBP                  W4,          W,          34      NK#  	  pp\	        V4      p\	        V4      p\        VP                  ^ ,          4       F  pWtR3,          W„R3,          3x € K  	  R# u upi u upi 5i)zî
Given the coordinates of a region like a=[0, 0] and b=[1, 1], yield the coordinates
of all subregions, which in this case would be::

    ([0, 0], [1/2, 1/2]),
    ([0, 1/2], [1/2, 1]),
    ([1/2, 0], [1, 1/2]),
    ([1/2, 1/2], [1, 1])
N.)r   ÚrangeÚshaperf   rZ   )	r   r   r   Úsplit_atÚiÚleftÚrightÚa_subÚb_subs	   &&&&     r   r   r   Ã  sÓ   é € ô 
˜Ó	€BàÒØ•E˜Q•;ˆä38¸¿¹À½Ô3DÓEÑ3D¨a�H‰H�a•d˜H�KÐ(Ö)Ñ3D€DÐEÜ49¸!¿'¹'À!½*Ô4EÓFÑ4E¨q�X‰X�x•{ A¥DÐ)Ö*Ñ4E€EÐFä˜tÓ$€EÜ˜uÓ%€Eä�5—;‘;˜q•>Ö"ˆØ�s�F�m˜U c 6�]Ð*Ô*ó #ùò FùÚFùs   ‚=D
¿'D Á& D
Â'DÂ-AD
c                 ól  € VP                   pVP                  W74      pVP                  WG4      pVP                  ^8X  d
   VR,          pVP                  R,          p\	        V4      p	\	        V4      p
W‰8w  g   WŠ8w  d   \        RV RV	 RV
 24      hW!,
          pV^,           VR,          ,          V,           pVP                  W·R7      ^V,          ,          pWM,          pV ! V.VO5!  pVP                  VR.^.VP                  ^,
          ,          O54      pVP                  VV,          ^ VR7      pV# )	é   z@rule and function are of incompatible dimension, nodes havendim z,, while limit of integration has ndima_ndim=z	, b_ndim=g      à?)Údtype)rH   rv   ):NNNNrY   )	rv   ÚastypeÚndimrm   r   rS   r[   re   Úsum)r   r   r   Ú
orig_nodesÚorig_weightsr   r   Úresult_dtypeÚ	rule_ndimÚa_ndimÚb_ndimÚlengthsr6   Úweight_scale_factorr7   Úf_nodesÚweights_reshapedr   s   &&&&&&&           r   r5   r5   Ü  s5  € à—7‘7€LØ—‘˜:Ó4€JØ—9‘9˜\Ó8€Lð ‡�˜!ÔØ Õ(ˆ
à× Ñ  Õ$€Iä�Q‹Z€FÜ�Q‹Z€FàÔ˜iÔ1Üð !Ø!* ð ,#Ø#) (¨)°F°8ð=ó >ð 	>ð �e€Gð ˜!�^ ¨#¥Õ.°Õ2€Eð Ÿ'™' '˜'Ó>ÀÀIÅÕMÐØÕ0€Gá�ˆo˜‹o€GØ—z‘z '¨BÐ+L°1°#¸¿¹ÈÕ9IÕ2JÑ+LÓMÐð
 �&‰&Ð! GÕ+°!¸<ˆ&Ó
H€Cà€Jr   r,   )Úscipy._lib._array_apir   r   Ú	functoolsr   r   r*   r;   rP   rZ   r   r5   r   r   r   Ú<module>r†      sV   ðß :å %÷Q.ñ Q.ôhXI�ô XIôvh
�iô h
ôVW˜ô Wòtô+ô2*r   