a
    ‡ù»j,3  ã                   @   s¢   d dl Z d dlZd dlZd dlZd dlmZ ddlmZ d dl	m
  mZ d dlmZ ddlmZ dgZdd	„ ZG d
d„ dƒZejfdd„Zdejdœdd„ZdS )é    N)Úprodé   )Ú_bspl)Ú	csr_array)Ú_not_a_knotÚ	NdBSplinec                 C   s   t  | t j¡rt jS t jS dS )z>Return np.complex128 for complex dtypes, np.float64 otherwise.N)ÚnpÚ
issubdtypeÚcomplexfloatingZ
complex128Zfloat64©Údtype© r   úBE:\soccer\ml_env\Lib\site-packages\scipy/interpolate/_ndbspline.pyÚ
_get_dtype   s    r   c                   @   s<   e Zd ZdZddœdd„Zdddœdd„Zedd
d„ƒZdS )r   a©  Tensor product spline object.

    The value at point ``xp = (x1, x2, ..., xN)`` is evaluated as a linear
    combination of products of one-dimensional b-splines in each of the ``N``
    dimensions::

       c[i1, i2, ..., iN] * B(x1; i1, t1) * B(x2; i2, t2) * ... * B(xN; iN, tN)


    Here ``B(x; i, t)`` is the ``i``-th b-spline defined by the knot vector
    ``t`` evaluated at ``x``.

    Parameters
    ----------
    t : tuple of 1D ndarrays
        knot vectors in directions 1, 2, ... N,
        ``len(t[i]) == n[i] + k + 1``
    c : ndarray, shape (n1, n2, ..., nN, ...)
        b-spline coefficients
    k : int or length-d tuple of integers
        spline degrees.
        A single integer is interpreted as having this degree for
        all dimensions.
    extrapolate : bool, optional
        Whether to extrapolate out-of-bounds inputs, or return `nan`.
        Default is to extrapolate.

    Attributes
    ----------
    t : tuple of ndarrays
        Knots vectors.
    c : ndarray
        Coefficients of the tensor-produce spline.
    k : tuple of integers
        Degrees for each dimension.
    extrapolate : bool, optional
        Whether to extrapolate or return nans for out-of-bounds inputs.
        Defaults to true.

    Methods
    -------
    __call__
    design_matrix

    See Also
    --------
    BSpline : a one-dimensional B-spline object
    NdPPoly : an N-dimensional piecewise tensor product polynomial

    N)Úextrapolatec                C   sF  t |ƒ}zt |ƒ W n ty0   |f| }Y n0 t |ƒ|kr\tdt |ƒ›dt |ƒ›d�ƒ‚tdd„ |D ƒƒ| _tdd„ |D ƒƒ| _t |¡| _|d u rœd}t	|ƒ| _
t |¡| _t|ƒD �]f}| j| }| j| }|jd | d	 }	|dk rþtd
|› d�ƒ‚|jd	k�rtd|› d�ƒ‚|	|d	 k �rLtdd| d › d|› d|› d�ƒ‚t |¡dk  ¡ �rptd|› d�ƒ‚t t |||	d	 … ¡ƒdk �r td|› d�ƒ‚t |¡ ¡ �sÀtd|› d�ƒ‚| jj|k �rÞtd|› d�ƒ‚| jj| |	krºtd|› d| jj| › dt |ƒ› d|	› d|› d�ƒ‚qºt| jjƒ}
tj| j|
d�| _d S )Nz	len(t) = z != len(k) = Ú.c                 s   s   | ]}t  |¡V  qd S ©N)ÚoperatorÚindex)Ú.0Zkir   r   r   Ú	<genexpr>Y   ó    z%NdBSpline.__init__.<locals>.<genexpr>c                 s   s   | ]}t j|td �V  qdS ©r   N)r   ÚascontiguousarrayÚfloat©r   Útir   r   r   r   Z   r   Tr   r   zSpline degree in dimension z cannot be negative.zKnot vector in dimension z must be one-dimensional.zNeed at least é   z knots for degree z in dimension zKnots in dimension z# must be in a non-decreasing order.z.Need at least two internal knots in dimension z should not have nans or infs.zCoefficients must be at least z-dimensional.z,Knots, coefficients and degree in dimension z are inconsistent: got z coefficients for z knots, need at least z for k=r   )ÚlenÚ	TypeErrorÚ
ValueErrorÚtupleÚkÚtr   ÚasarrayÚcÚboolr   ÚrangeÚshapeÚndimÚdiffÚanyÚuniqueÚisfiniteÚallr   r   r   )Úselfr#   r%   r"   r   r)   ÚdÚtdÚkdÚnÚdtr   r   r   Ú__init__M   sl    


ÿÿ
 ÿ
ÿ
ÿ
þýýüzNdBSpline.__init__)Únur   c                   s^  t | jƒ}|du r| j}t|ƒ}|du r<tj|ftjd�}n^tj|tjd�}|jdksd|j	d |kr€t
d|›dt | jƒ› d�ƒ‚t|dk ƒršt
d|›�ƒ‚tj|td�}|j	}| d	|d	 ¡}t |¡}|d	 |krèt
d
|› d|› �ƒ‚tj| jt d¡d�}dd„ | jD ƒ}tj|t|ƒftd�}| tj¡ t|ƒD ]&}	| j|	 ||	dt | j|	 ƒ…f< �q8tj|t d¡d�}tdd„ | jD ƒƒ}
t t t|
ƒ¡|
¡}tj|tjd�j}| j | jj	d|… d ¡‰ ˆ  ¡ }tj‡ fdd„ˆ jD ƒtjd�}ˆ j	d	 }tj|j	dd	… |f ˆ jd�}t  |||||||||||¡ | |dd	… | jj	|d…  ¡S )a@  Evaluate the tensor product b-spline at ``xi``.

        Parameters
        ----------
        xi : array_like, shape(..., ndim)
            The coordinates to evaluate the interpolator at.
            This can be a list or tuple of ndim-dimensional points
            or an array with the shape (num_points, ndim).
        nu : array_like, optional, shape (ndim,)
            Orders of derivatives to evaluate. Each must be non-negative.
            Defaults to the zeroth derivivative.
        extrapolate : bool, optional
            Whether to exrapolate based on first and last intervals in each
            dimension, or return `nan`. Default is to ``self.extrapolate``.

        Returns
        -------
        values : ndarray, shape ``xi.shape[:-1] + self.c.shape[ndim:]``
            Interpolated values at ``xi``
        Nr   r   r   z)invalid number of derivative orders nu = z for ndim = r   z'derivatives must be positive, got nu = éÿÿÿÿzShapes: xi.shape=z
 and ndim=Úlongc                 S   s   g | ]}t |ƒ‘qS r   ©r   r   r   r   r   Ú
<listcomp>¹   r   z&NdBSpline.__call__.<locals>.<listcomp>c                 s   s   | ]}|d  V  qdS )r   Nr   )r   r2   r   r   r   r   Á   r   z%NdBSpline.__call__.<locals>.<genexpr>)r7   c                    s   g | ]}|ˆ j j ‘qS r   )r   Úitemsize)r   Ús©Úc1r   r   r:   Ê   s   ÿ)!r   r#   r   r&   r   ZzerosZintcr$   r)   r(   r    r+   r   Úreshaper   r"   r   ÚemptyÚmaxÚfillÚnanr'   r!   Zunravel_indexZaranger   ZintpÚTr%   ZravelÚstridesr   Zevaluate_ndbspline)r/   Úxir6   r   r)   Úxi_shapeZ_kZlen_tZ_tr0   r(   ÚindicesZ_indices_k1dZc1rZ_strides_c1Znum_c_trÚoutr   r=   r   Ú__call__†   sj    
ÿÿ
$ÿÿ
 özNdBSpline.__call__Tc           
      C   sš   t j|td�}|jd }t|ƒ|kr>tdt|ƒ› d|›d�ƒ‚zt|ƒ W n tyf   |f| }Y n0 t j|t jd�}t 	|||¡\}}}	t
|||	fƒS )a  Construct the design matrix as a CSR format sparse array.

        Parameters
        ----------
        xvals :  ndarray, shape(npts, ndim)
            Data points. ``xvals[j, :]`` gives the ``j``-th data point as an
            ``ndim``-dimensional array.
        t : tuple of 1D ndarrays, length-ndim
            Knot vectors in directions 1, 2, ... ndim,
        k : int
            B-spline degree.
        extrapolate : bool, optional
            Whether to extrapolate out-of-bounds values of raise a `ValueError`

        Returns
        -------
        design_matrix : a CSR array
            Each row of the design matrix corresponds to a value in `xvals` and
            contains values of b-spline basis elements which are non-zero
            at this value.

        r   r7   z*Data and knots are inconsistent: len(t) = z for  ndim = r   )r   r$   r   r(   r   r    r   Zint32r   Z
_colloc_ndr   )
ÚclsÚxvalsr#   r"   r   r)   ÚkkÚdatarH   Zindptrr   r   r   Údesign_matrixÞ   s    
ÿÿzNdBSpline.design_matrix)T)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r5   rJ   ÚclassmethodrO   r   r   r   r   r      s
   29Xc           	   	   K   s  t  |jt j¡rHt| |j|fi |¤Ž}t| |j|fi |¤Ž}|d|  S |jdkrÔ|jd dkrÔt  	|¡}t
|jd ƒD ]V}|| |d d …|f fi |¤Ž\|d d …|f< }|dkrxtd|›d|›d|› d�ƒ‚qx|S || |fi |¤Ž\}}|dk�r
td|›d	|›d�ƒ‚|S d S )
Ny              ð?r   r   r   z	solver = z returns info =z for column r   z returns info = )r   r	   r   r
   Ú_iter_solveÚrealÚimagr)   r(   Z
empty_liker'   r    )	ÚaÚbÚsolverÚsolver_argsrV   rW   ÚresÚjÚinfor   r   r   rU     s    
.
rU   é   ©rZ   c                   sv  t ˆƒ}tdd„ ˆD ƒƒ}zt ˆ ƒ W n tyB   ˆ f| ‰ Y n0 tˆƒD ]P\}}t t |¡ƒ}	|	ˆ | krLtd|	› d|› dˆ | › dˆ | d › d�	ƒ‚qLt‡ ‡fd	d„t|ƒD ƒƒ}
tjd
d„ t	j
ˆŽ D ƒtd�}t ||
ˆ ¡}|j}t|d|… ƒt||d… ƒf}| |¡}|tjk�rBtjt|d�}d|v�rBd|d< |||fi |¤Ž}| |||d…  ¡}t|
|ˆ ƒS )a™  Construct an interpolating NdBspline.

    Parameters
    ----------
    points : tuple of ndarrays of float, with shapes (m1,), ... (mN,)
        The points defining the regular grid in N dimensions. The points in
        each dimension (i.e. every element of the `points` tuple) must be
        strictly ascending or descending.      
    values : ndarray of float, shape (m1, ..., mN, ...)
        The data on the regular grid in n dimensions.
    k : int, optional
        The spline degree. Must be odd. Default is cubic, k=3
    solver : a `scipy.sparse.linalg` solver (iterative or direct), optional.
        An iterative solver from `scipy.sparse.linalg` or a direct one,
        `sparse.sparse.linalg.spsolve`.
        Used to solve the sparse linear system
        ``design_matrix @ coefficients = rhs`` for the coefficients.
        Default is `scipy.sparse.linalg.gcrotmk`
    solver_args : dict, optional
        Additional arguments for the solver. The call signature is
        ``solver(csr_array, rhs_vector, **solver_args)``

    Returns
    -------
    spl : NdBSpline object

    Notes
    -----
    Boundary conditions are not-a-knot in all dimensions.
    c                 s   s   | ]}t |ƒV  qd S r   r9   )r   Úxr   r   r   r   @  r   zmake_ndbspl.<locals>.<genexpr>z
There are z points in dimension z, but order z requires at least  r   z points per dimension.c                 3   s*   | ]"}t tjˆ| td �ˆ | ƒV  qdS r   )r   r   r$   r   )r   r0   ©r"   Úpointsr   r   r   O  s   ÿc                 S   s   g | ]}|‘qS r   r   )r   Zxvr   r   r   r:   Q  r   zmake_ndbspl.<locals>.<listcomp>r   Nr`   Zatolg�íµ ÷Æ°>)r   r!   r   Ú	enumerater   Z
atleast_1dr    r'   r$   Ú	itertoolsÚproductr   r   rO   r(   r   r?   ÚsslZspsolveÚ	functoolsÚpartialrU   )rc   Úvaluesr"   rZ   r[   r)   rG   r0   ÚpointZnumptsr#   rL   ZmatrZv_shapeZ
vals_shapeÚvalsZcoefr   rb   r   Úmake_ndbspl   s:    ÿ
þÿ 

rm   )r_   )re   rh   r   Únumpyr   Úmathr   Ú r   Zscipy.sparse.linalgÚsparseZlinalgrg   Zscipy.sparser   Z	_bsplinesr   Ú__all__r   r   ZgcrotmkrU   rm   r   r   r   r   Ú<module>   s    o