Ë
    ÏÍ:jó¤  ã                   óø   — d Z ddlZddlmZ ddlmZmZmZm	Z	 ddl
mZ ddlmZ ddlmZ d!d	„Zd
„ Z G d„ d«      Zd„ Z	 d"d„Z G d„ d«      Zddddœd„Zd„ Zd„ Zd#d„ZdZd„ Zddddddddœd„Zddddddœd „Zy)$u¨  
Regrid (2-D smoothing B-splines via separable 1-D FITPACK kernels)
==================================================================

1) Overview
-----------
This module fits a bivariate tensor-product B-spline surface to gridded data
`Z[i, j]` sampled on strictly increasing coordinates `x[i]`, `y[j]`. It mirrors
the adaptive spirit of FITPACK's REGRID/fpgrre (knot growth + smoothing
parameter search to meet a target residual `s`) while keeping the control flow
explicit in Python and returning a 2-D `NdBSpline`.

**Key conventions**
- **Penalty scaling is 1/p** - *same as FITPACK*. The augmented system stacks
  `(D / p)` under the data matrix. Smaller `p` -> stronger smoothing; larger `p`
  -> weaker smoothing (approaching interpolation).
- `p == -1` is used **as a sentinel for `p = âˆž`** (interpolatory limit): when
  seen, the solver omits penalty rows entirely.

2) Mathematics (and how this differs from FITPACK's REGRID)
-----------------------------------------------------------
Let `A_x`, `A_y` be banded 1-D design matrices and `D_x`, `D_y` the banded
1-D roughness (difference) matrices returned by FITPACK/Dierckx's 1-D APIs
(`data_matrix`, `disc`). The 2-D smoothing objective is

    minimize  ||A c - z||^2 + (1/p) ||D c||^2,            (1)

implemented by the **augmented** least squares system

    [ A ] c ~ [ z ]
    [D/p]     [ 0 ].

**Same as FITPACK:** Equation (1) uses the *1/p* convention.
**Different in this module:** We realize the 2-D problem by composing **1-D**
banded operators in two separable passes (x then y), instead of calling a
monolithic 2-D routine. This makes the mathematics transparent while producing
the same normal equations structure that REGRID targets internally.

3) Residual energy: definition and use
--------------------------------------
After solving on the current knots (initially at the interpolatory limit,
`p = âˆž`), we evaluate the surface and form

    R = Z - Zhat,                         fp = sum(R[i, j]^2).

We then **project** residual energy to knot spans along each axis:

- Row energy  `row_energy[i] = sum(R[i, j]^2, j)`  -> accumulated into `fpintx`.
- Column energy `col_energy[j] = sum(R[i, j]^2, i)` -> accumulated into `fpinty`.

These per-span energies guide **adaptive knot insertion**: the algorithm picks
high-energy spans (skipping zero-length ones) and inserts data-aligned knots
(e.g., median sample within the span), with simple batch sizing and headroom
limits. This is conceptually the same idea as REGRID's `fpint` arrays; here it
is implemented explicitly and vectorized in Python for clarity.

4) Solver used here vs. FITPACK's REGRID
----------------------------------------
**This module (separable 1-D composition):**
- Uses **1-D FITPACK/Dierckx kernels** (`data_matrix`, `disc`, `qr_reduce`,
  `fpback`) to solve 2-D via two passes:
  1) augment/QR/backsolve along **x**, producing an intermediate;
  2) augment/QR/backsolve along **y**, producing the coefficient grid `C`.
- The augmented rows are stacked as `[A; D/p]` (1/p scaling, **same as FITPACK**).
- If `fp > s` after knot growth, performs a **scalar search in `p`** using a
  ratio-of-roots routine; `p == -1` is treated as `p = âˆž` for the interpolatory
  reference without penalty rows.

**FITPACK REGRID (monolithic 2-D routine):**
- Implements the same mathematical objective and **1/p** penalty scaling,
  but inside a specialized, fully 2-D Fortran routine with in-place Givens/QR
  and a rational update for `p`.
- Handles residual partitioning, knot insertion, and `p` updates internally.

**Practical difference:** We build the 2-D solve from **1-D building blocks**,
which keeps each stage observable/testable and uses the same low-level kernels
as FITPACK, but without relying on the single monolithic REGRID entry point.

5) Execution flow (who calls whom)
----------------------------------

**Top-level**
1. `_regrid`
   - Validates shapes/monotonicity and normalizes `bbox`.
   - Dispatches to `_regrid_fitpack(...)`.

**Core driver**
2. `_regrid_fitpack`
   - Clips inputs to `bbox` via `_apply_bbox_grid` -> `(x_fit, y_fit, Z_fit)`.
   - If `s == 0` (interpolation path):
     - Build initial not-a-knot vectors: `tx = _not_a_knot(x_fit, kx)`,
       `ty = _not_a_knot(y_fit, ky)`.
     - Build design matrices: `(Ax, Ay, Q) = build_design_matrices(...)`.
     - Solve once at `p = -1` (inf): `C0, fp = _solve_2d_fitpack(...)`.
     - Return `return_NdBSpline(...)`.
   - Else (`s > 0`, smoothing with adaptive knots):
     - Initialize clamped no-interior-knot vectors with
       `_initialise_knots` (for x and y).
     - **Knot-growth loop** (up to `len(x_fit)+len(y_fit)` iterations):
       1) Build design matrices: `(Ax, Ay, Q) = build_design_matrices(...)`.
       2) Interpolatory reference solve (`p = -1`): `C0, fp = _solve_2d_fitpack(...)`.
       3) If both `tx`, `ty` are at minimal size, record `fp0 = fp`
          (used to bracket the p-search).
       4) If `fp < s`: **stop growth** and proceed to p-search / finalize.
       5) Compute residuals for knot insertion:
          - Convert packed to CSR once per axis for evaluation:
            `_Ax = Ax.tocsr(...)`, `_Ay = Ay.tocsr(...)`
          - Evaluate `Z0 = _Ax @ C0 @ _Ay.T`, residual `R = Z_fit - Z0`.
       6) Insert knots on alternating axes using energy heuristics:
          - If last axis was `y`, grow `tx` with
            `_add_knots(..., residuals=np.sum(R**2, axis=1), ...)`.
          - Else, grow `ty` with `_add_knots(..., residuals=np.sum(R**2, axis=0), ...)`.
          - Update `fpold`, `nplus{ x|y }`, `last_axis`.
     - If growth ended with both axes still minimal: return `return_NdBSpline(...)`.
     - **Finite-p smoothing (if needed):**
       - Build 1-D penalty operators: `(Drx, _, ncx) = disc(tx, kx)`,
         `(Dry, _, ncy) = disc(ty, ky)`, wrap as `PackedMatrix`.
       - Rebuild design matrices on the final `(tx, ty)`.
       - Run `_p_search_hit_s(...)` to find `p*` such that `fp(p*) ~ s`:
         - Internally constructs `F(...)` which evaluates `fp(p)`
           by calling `_solve_2d_fitpack(...)`.
         - Uses `root_rati` on `g(p) = fp(p) - s` with the interpolatory
           reference at `p = inf` and `fp0` bracket.
       - Return `return_NdBSpline(...)`.

**Separable solver (used by both interpolation and p-search)**
3. `_solve_2d_fitpack`
   - Forms augmented banded systems via `_stack_augmented_fitpack`:
     - X-side: `Ax_aug = [Ax; Dx/p]` if `p != -1`, else just `Ax`.
     - Y-side: `Ay_aug = [Ay; Dy/p]` if `p != -1`, else just `Ay`.
     - Pads RHS `Q` with zeros when penalties are stacked.
   - **Stage X**: `_dierckx.qr_reduce(Ax_aug, ...)` then
     `_dierckx.fpback(...)` -> intermediate `T`.
   - Transpose `T` to feed Y solves column-wise; pad if needed.
   - **Stage Y**: `_dierckx.qr_reduce(Ay_aug, ...)` then
     `_dierckx.fpback(...)` -> coefficients `C`.
   - Build CSR design matrices once: `_Ax = Ax.tocsr(...)`, `_Ay = Ay.tocsr(...)`.
   - Evaluate `zhat = _Ax @ C.T @ _Ay.T`, compute `fp = ||Z_fit - zhat||^2`.
   - Return `C.T` (in `(nx_coef, ny_coef)` layout) and `fp`.

**Helpers**
- `_apply_bbox_grid(...)` - slices to `(x_fit, y_fit, Z_fit)`.
- `build_design_matrices(...)` - wraps `_dierckx.data_matrix` and
  returns `PackedMatrix` wrappers + `Q`.
- `_initialise_knots(...)`, `_add_knots(...)` - FITPACK-style knot bookkeeping/growth.
- `disc(...)` - 1-D roughness operators (packed band form).
- `F` + `root_rati` - maps `p -> fp(p)` and finds `p*` with `fp(p*) ~ s`.
- `return_NdBSpline(...)` - packs `(tx, ty, C)` into an `NdBSpline`.
é    N)Ú	NdBSpline)Ú	root_ratiÚdiscÚadd_knotÚ_not_a_knoté   )Ú_dierckx)Ú	csr_array)Ú_validate_intc                 ój  — t        | j                  «      dk7  rt        d«      ‚t        |d«      }t        |d«      }|dk  s|dk  rt        d«      ‚| j                  j
                  dd }t        j                  |«      }t        j                  |«      }|�r;|j                  dk(  s|j                  dk(  rFt        j                  |j                  |j                  f|z   | j                  j                  ¬«      }|S |j                  dk\  r6t        j                  t        j                  |«      d	k\  «      st        d
«      ‚|j                  dk\  r6t        j                  t        j                  |«      d	k\  «      st        d«      ‚t        j                  ||d¬«      \  }}	t        j                  ||	fd¬«      }
 | |
||f| j                  ¬«      }|S |j
                  |j
                  k7  rt        j                   ||«      \  }}|j                  dk(  r8t        j                  |j
                  |z   | j                  j                  ¬«      S t        j                  |j#                  «       |j#                  «       fd¬«      }
 | |
||f| j                  ¬«      }|j%                  |j
                  |z   «      S )aC  
    Evaluate a 2D `NdBSpline` like a classical bivariate API.

    Parameters
    ----------
    ndbs : NdBSpline
        A 2D spline object (``len(ndbs.t) == 2``).
    x, y : array_like
        Sample locations. If ``grid=True``, these must be 1-D strictly
        increasing vectors. If ``grid=False``, they can be broadcastable
        arrays of the same shape.
    dx, dy : int, optional
        Derivative orders along `x` and `y` respectively, by default 0.
    grid : bool, optional
        If True, evaluate on the cartesian product of `x` and `y`;
        otherwise treat `(x, y)` as paired coordinates, by default True.

    Returns
    -------
    ndarray or (ndarray, dict)
        Evaluated values with shape:
        - ``(len(x), len(y), ...)`` if ``grid=True``.
        - ``x.shape + ...`` if ``grid=False``.

    Raises
    ------
    ValueError
        If `ndbs` is not 2D, derivatives are negative, or monotonicity checks fail.

    Notes
    -----
    This is a thin convenience wrapper around ``NdBSpline.__call__`` with input
    validation and optional profiling.
    é   z*ndbs must be a 2D NdBSpline (len(t) == 2).ÚdxÚdyr   z,order of derivative must be positive or zeroN©Údtypeç        z1x must be strictly increasing when `grid` is Truez1y must be strictly increasing when `grid` is TrueÚij)Úindexingéÿÿÿÿ©Úaxis)ÚnuÚextrapolate)ÚlenÚtÚ
ValueErrorr   ÚcÚshapeÚnpÚasarrayÚsizeÚzerosr   ÚallÚdiffÚmeshgridÚstackr   Úbroadcast_arraysÚravelÚreshape)ÚndbsÚxÚyr   r   ÚgridÚtrailingÚvalsÚXÚYÚxis              ún/home/mcse/projects/srt_converter/srt-converter-venv/lib/python3.12/site-packages/scipy/interpolate/_regrid.pyÚ_ndbspline_call_like_bivariater4   ž   s  € ôF ˆ4�6‰6ƒ{�aÒÜÐEÓFÐFä	�r˜4Ó	 €BÜ	�r˜4Ó	 €BØ	ˆA‚v��a’ÜÐGÓHÐHà�v‰v�|‰|˜A˜BÐ€HÜ
�
‰
�1‹€AÜ
�
‰
�1‹€AâØ�6‰6�QŠ;˜!Ÿ&™& Aš+Ü—8‘8˜QŸV™V Q§V¡VÐ,¨xÑ7¸t¿v¹v¿|¹|ÔLˆDØˆKà�F‰F�aŠK¤"§&¡&¬¯©°«°sÑ):Ô";ÜÐPÓQÐQØ�F‰F�aŠK¤"§&¡&¬¯©°«°sÑ):Ô";ÜÐPÓQÐQä�{‰{˜1˜a¨$Ô/‰ˆˆ1Ü�X‰X�q˜!�f 2Ô&ˆá�B˜B ˜8°×1AÑ1AÔBˆàˆà�7‰7�a—g‘gÒÜ×&Ñ& q¨!Ó,‰DˆAˆqà�6‰6�QŠ;Ü—8‘8˜AŸG™G hÑ.°d·f±f·l±lÔCÐCÜ�X‰X�q—w‘w“y !§'¡'£)Ð,°2Ô6ˆÙ�B˜B ˜8°×1AÑ1AÔBˆØ�|‰|˜AŸG™G hÑ.Ó/Ð/ó    c                 ó°   — t        |d   «      t        |d   «      }}|\  }}|d   j                  ||z
  dz
  ||z
  dz
  «      }t        |d   |d   f||«      S )a›  
    Build a 2D ``NdBSpline`` from knot vectors and a coefficient grid.

    Parameters
    ----------
    fp : float
        Residual sum of squares of the produced fit (kept for upstream use).
    tck : tuple
        Tuple ``(tx, ty, C)`` where ``tx``, ``ty`` are knot vectors and ``C``
        is a coefficient array with shape ``(nx - kx - 1, ny - ky - 1)`` or
        a compatible shape that can be reshaped to that.
    degrees : tuple of int
        Degrees ``(kx, ky)`` along x and y.

    Returns
    -------
    NdBSpline
        The constructed 2D spline.

    Notes
    -----
    Only repacks the coefficient grid; ``fp`` is not used internally here.
    r   r   r   )r   r)   r   )ÚfpÚtckÚdegreesÚnxÚnyÚkxÚkyr   s           r3   Úreturn_NdBSpliner>   è   sf   € ô0 ��Q‘‹[œ#˜c !™f›+ˆ€BØ�F€BˆØˆA‰�‰�r˜B‘w ‘{ B¨¡G¨a¡KÓ0€AÜ�c˜!‘f˜c !™fÐ% q¨'Ó2Ð2r5   c                   ó2   — e Zd ZdZd„ Zed„ «       Zd„ Zd„ Zy)ÚPackedMatrixas  A simplified CSR format for when non-zeros in each row are consecutive.

    Assuming that each row of an `(m, nc)` matrix 1) only has `nz` non-zeros, and
    2) these non-zeros are consecutive, we only store an `(m, nz)` matrix of
    non-zeros and a 1D array of row offsets. This way, a row `i` of the original
    matrix A is ``A[i, offset[i]: offset[i] + nz]``.

    c                 ó.   — || _         || _        || _        y ©N)ÚaÚoffsetÚnc)ÚselfrC   rD   rE   s       r3   Ú__init__zPackedMatrix.__init__  s   € ØˆŒØˆŒØˆ�r5   c                 óL   — | j                   j                  d   | j                  fS )Nr   )rC   r   rE   )rF   s    r3   r   zPackedMatrix.shape  s   € à�v‰v�|‰|˜A‰ §¡Ð'Ð'r5   c                 ój  — t        j                  | j                  «      }| j                  j                  d   }t	        |j                  d   «      D ]_  }t        | j                  | j                  |   z
  |«      }| j                  |d |…f   ||| j                  |   | j                  |   |z   …f<   Œa |S )Nr   r   )r   r"   r   rC   ÚrangeÚminrE   rD   )rF   ÚoutÚnelemÚiÚnels        r3   ÚtodensezPackedMatrix.todense  s    € Ü�h‰h�t—z‘zÓ"ˆØ—‘—‘˜Q‘ˆÜ�s—y‘y ‘|Ó$ò 	JˆAÜ�d—g‘g §¡¨A¡Ñ.°Ó6ˆCØ:>¿&¹&ÀÀDÀSÀDÀ¹/ˆC��4—;‘;˜q‘> $§+¡+¨a¡.°3Ñ"6Ð6Ð6Ò7ð	Jð ˆ
r5   c                 óÆ  — | j                   j                  «       }t        j                  | j                  |dz   «      j                  d|dz   «      }|t        j                  |dz   | j                  j                  ¬«      z   }|j                  «       }t        j                  d|dz   |dz   z  |dz   | j                  j                  ¬«      }t        |||f|||z
  dz
  f¬«      S )Nr   r   r   r   )r   )	rC   r(   r   ÚrepeatrD   r)   Úaranger   r
   )rF   ÚkÚmÚlen_tÚdataÚindicesÚindptrs          r3   ÚtocsrzPackedMatrix.tocsr   sÅ   € à�v‰v�|‰|‹~ˆô —)‘)˜DŸK™K¨¨1©Ó-×5Ñ5°b¸!¸A¹#Ó>ˆØœBŸI™I a¨¡c°·±×1BÑ1BÔCÑCˆØ—-‘-“/ˆä—‘˜1˜q 1™u¨¨Q©Ñ/°°Q±Ø!%§¡×!2Ñ!2ô4ˆô Ø�7˜FÐ#Ø�e˜a‘i !‘mÐ$ôð 	r5   N)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__rG   Úpropertyr   rP   rZ   © r5   r3   r@   r@     s*   „ ñòð
 ñ(ó ð(òór5   r@   c                 ó¬  — |dk(  r5| j                   j                  «       | j                  j                  «       |fS |dz   }t        j                  ||j
                  d   z   |dz   ft        ¬«      }| j                   d|…dd…f   |d|…d|…f<   |j                   |z  ||d…dd…f<   t        j                  | j                  |j                  f«      }|||fS )aê  
    Builds augmented banded matrix.

    Parameters
    ----------
    A : PackedMatrix
        Banded data/design matrix for one axis (from `_dierckx.data_matrix`).
    D : PackedMatrix
        Banded roughness (difference) penalty matrix for the same axis
        (from `disc`).
    nc : int
        Number of top (data) rows from `A` to include.
    k : int
        Spline degree (used only for sizing in the current implementation).
    p : float
        Smoothing parameter. The effective penalization term is scaled as **1/p**:
        larger `p` means *less* smoothing (approaching interpolation).
        If `p == -1`, it signals *p -> inf*, i.e. a pure interpolatory system
        with **no** penalty rows appended.

    Returns
    -------
    AA : ndarray
        Augmented banded matrix with `A` stacked over `(D / p)` when `p != -1`.
    offset : ndarray
        Concatenated band offsets for the augmented matrix.
    nc : int
        Returned unchanged for downstream convenience.
    r   r   r   r   r   N)rC   ÚcopyrD   r   r"   r   ÚfloatÚconcatenate)ÚAÚDrE   rT   ÚpÚnzÚAArD   s           r3   Ú_stack_augmented_fitpackrj   2  s½   € ð< 	ˆB‚wØ�s‰s�x‰x‹z˜1Ÿ8™8Ÿ=™=›?¨BÐ.Ð.à	
ˆQ‰€BÜ	�‰�2˜Ÿ™ ™
‘? A¨¡EÐ*´%Ô	8€BØ—3‘3�s˜�sšA�v‘;€B€sˆ€sˆCˆRˆC€x�LØ—‘�q‘€B€r�sŠA€v�JÜ�^‰^˜QŸX™X q§x¡xÐ0Ó1€FØˆv�rˆ>Ðr5   c                 óÀ  — t        j                  |«      }t        j                  |	«      }t        | || j                  d   ||«      \  }}}| j                  }t        |||j                  d   ||«      \  }}}|j                  }|dk7  rLt        j
                  |t        j                  |j                  d   |j                  d   ft        ¬«      g«      }t        j                  ||||«       t        j                  ||||||||d«	      \  }}}t        j                  |j                  «      }|dk7  rLt        j
                  |t        j                  |j                  d   |j                  d   ft        ¬«      g«      }t        j                  ||||«       t        j                  |||	|||||d«	      \  }}}| j                  ||j                  d   t        |«      «      }|j                  ||	j                  d   t        |«      «      }||j                  z  |j                  z  }|
|z
  }t        j                  t        j                   |«      «      }|j                  ||fS )aÑ  
    Solve the 2-D tensor-product spline system using separable banded QR.

    ================================================================
    Mathematical model (step by step, plain text)
    ================================================================

    Shapes:
        Z      : (mx, my)  -> original data
        Ax, Ay : design matrices for x and y
        Dx, Dy : roughness penalty matrices for x and y
        C      : (nx, ny)  -> spline coefficients to solve for

    Surface approximation:
        Zhat = Ax * C * Ay^T

    Objective (smoothing formulation):
        minimize ||Ax*C*Ay^T - Z||^2 + (1/p)*(||Dx*C||^2 + ||C*Dy^T||^2)

    In practice (FITPACK-style separable approach), we solve this in two stages:

    --------------------------------------------------------
    Stage 1 (x-direction solve for all y-columns together):
    --------------------------------------------------------

        For each column of Z:
            minimize ||Ax*T - Z||^2 + (1/p)*||Dx*T||^2

        This is equivalent to the augmented least-squares system:
            [Ax]       [Z]
            [Dx/p] * T = [0]

        i.e.  minimize || [Ax; Dx/p]*T - [Z; 0] ||^2

        The solution T is obtained by QR reduction and back-substitution.

    --------------------------------------------------------
    Stage 2 (y-direction solve using transposed result):
    --------------------------------------------------------
        Now treat T^T as the new RHS for the y-direction:
            minimize ||Ay*C^T - T^T||^2 + (1/p)*||Dy*C^T||^2

        Equivalent to augmented system:
            [Ay]       [T^T]
            [Dy/p] * C^T = [0]

        i.e.  minimize || [Ay; Dy/p]*C^T - [T^T; 0] ||^2

        Solving this gives C^T (then transposed back to C).

    --------------------------------------------------------
    Interpolation limit:
    --------------------------------------------------------
        If p == -1, penalties are omitted (Dx, Dy are not stacked).
        The solver behaves as a near-interpolating system.

    --------------------------------------------------------
    Residual computation:
    --------------------------------------------------------
        Zhat = Ax * C * Ay^T
        R    = Z - Zhat
        fp   = sum(R^2)

    Parameters
    ----------
    Ax, Ay : PackedMatrix
        Banded data matrices for the x and y axes.
    Q : ndarray, shape (mx, my)
        RHS data grid (copied from `Z`).
    p : float
        Smoothing parameter. The penalty term is scaled as **1/p**.
        Setting `p == -1` signals *p -> inf* (interpolation, omit penalty).
    kx, ky : int
        Spline degrees along x and y.
    tx, ty : ndarray
        Knot vectors along x and y.
    x_x, x_y : ndarray
        Sample coordinates.
    z : ndarray
        Original data grid for residual evaluation.
    Dx, Dy : ndarray
        Banded roughness penalty matrices for x and y.
        Optional, Only needed when ``p != -1``.

    Returns
    -------
    C : ndarray
        2-D B-spline coefficient grid.
    fp : float
        Residual sum of squares between fitted surface and `z`.
    R : ndarray, shape (mx, my)
        Residual matrix ``z - zhat``, where ``zhat = Ax @ C @ Ay.T``.

    Notes
    -----
    This performs two separable QR solves (x then y), each augmented by
    `(D / p)` when `p != -1`.  Setting `p = -1` skips all penalty rows,
    yielding an interpolatory surface.  The resulting coefficients and residual
    follow the same conventions as FITPACK's `fpgrre`.
    r   r   r   r   F)r   Ú	ones_likerj   r   rE   Úvstackr"   rc   r	   Ú	qr_reduceÚfpbackÚascontiguousarrayÚTrZ   r   ÚsumÚsquare)ÚAxÚAyÚQrg   r<   ÚtxÚx_xr=   ÚtyÚx_yÚzÚDxÚDyÚw_xÚw_yÚAx_augÚoffset_aug_xÚnc_augxÚnc_xÚAy_augÚoffset_aug_yÚnc_augyÚnc_yrq   Ú_ÚCr7   Ú_AxÚ_AyÚzhatÚRs                                  r3   Ú_solve_2d_fitpackrŽ   Z  s  € ôR �,‰,�sÓ
€CÜ
�,‰,�sÓ
€Cô %=Ø
ˆB�—‘˜‘˜R ó%$Ñ!€FˆL˜'à�5‰5€Dô %=Ø
ˆB�—‘˜‘˜R ó%$Ñ!€FˆL˜'à�5‰5€Dð 	ˆB‚wô �I‰I�qœ"Ÿ(™( B§H¡H¨Q¡K°·±¸±Ð#<ÄEÔJÐKÓLˆô ×Ñ�v˜|¨W°aÔ8ô �o‰oØ��cØ	ˆ2ˆr�3Ø	ˆ5ó�G€A€qˆ!ô 	×Ñ˜QŸS™SÓ!€Að 	ˆB‚wä�I‰I�qœ"Ÿ(™( B§H¡H¨Q¡K°·±¸±Ð#<ÄEÔJÐKÓLˆô ×Ñ�v˜|¨W°aÔ8ô �‰Ø�ØˆQ��B˜Ø	Øó	�H€A€qˆ"ð �(‰(�2�s—y‘y ‘|¤S¨£WÓ
-€CØ
�(‰(�2�s—y‘y ‘|¤S¨£WÓ
-€Cð �—‘‰9�s—u‘uÑ€Dð
 	
ˆD‰€AÜ	�‰”—	‘	˜!“Ó	€Bð �3‰3��Aˆ:Ðr5   c                   ó   — e Zd ZdZd„ Zd„ Zy)ÚFa—  
    Callable wrapper for computing `fp(p)` for a fixed spline configuration.

    Parameters
    ----------
    Ax, Ay : PackedMatrix
        Banded data matrices.
    Dx, Dy : PackedMatrix
        Banded penalty matrices.
    kx, ky : int
        Degrees along x and y.
    tx, ty : ndarray
        Knot vectors along x and y.
    x_x, x_y : ndarray
        Sample coordinates.
    w_x, w_y : ndarray
        Weights (usually ones).
    z : ndarray
        Data grid for computing the residual.

    Attributes
    ----------
    C : ndarray
        Coefficient matrix from the most recent solve.
    fp : float
        Residual value from the most recent solve.

    Notes
    -----
    The penalty is applied as **1/p**, so smaller `p` values yield heavier
    smoothing. Setting `p == -1` corresponds to *p = inf*, i.e. interpolation.
    Intended for use by `_p_search_hit_s` to iteratively evaluate `fp(p)`.
    c                 ó¬   — || _         || _        || _        || _        || _        || _        || _        || _        |	| _        |
| _	        || _
        || _        y rB   )rt   r|   ru   r}   rv   r<   rw   rx   r=   ry   rz   r{   )rF   rt   r|   ru   r}   rv   r<   rw   rx   r=   ry   rz   r{   s                r3   rG   z
F.__init__I  sX   € ð ˆŒØˆŒØˆŒØˆŒØˆŒØˆŒØˆŒØˆŒØˆŒØˆŒØˆŒØˆ�r5   c                 óf  — t        | j                  | j                  | j                  j	                  «       || j
                  | j                  | j                  | j                  | j                  | j                  | j                  | j                  | j                  ¬«      \  }}}|| _        || _        |S )N)r|   r}   )rŽ   rt   ru   rv   rb   r<   rw   rx   r=   ry   rz   r{   r|   r}   r‰   r7   )rF   rg   r‰   r7   rˆ   s        r3   Ú__call__z
F.__call__Y  s}   € ô
 %Ø�G‰G�T—W‘W˜dŸf™fŸk™k›mØˆt�w‰w˜Ÿ™ §¡Ø�G‰G�T—W‘W˜dŸh™h¨¯©Ø�w‰w˜4Ÿ7™7ô	$‰ˆˆ2ˆqð
 ˆŒØˆŒØˆ	r5   N)r[   r\   r]   r^   rG   r“   r`   r5   r3   r�   r�   &  s   „ ñ òDó r5   r�   g      ð?gü©ñÒMbP?é(   )Úp_initÚtol_relÚmaxitc                ó  ‡‡— t        | |||||||||	|
|«      Šˆˆfd„} |d«      }d|‰z
  ft        j                  |ff}t        ‰|z  d«      }t	        |||||¬«      }|j
                  } ‰|«      }‰j                  }|||fS )aÜ  
    Search for a smoothing parameter `p` such that `fp(p) ~ s`.

    Parameters
    ----------
    Ax, Ay : PackedMatrix
        Banded data matrices.
    Dx, Dy : PackedMatrix
        Banded penalty matrices.
    Q : ndarray
        RHS data grid (copy of `Z`).
    kx, ky : int
        Spline degrees.
    tx, ty : ndarray
        Knot vectors.
    x_x, x_y : ndarray
        Sample coordinates.
    w_x, w_y : ndarray
        Sample weights.
    z : ndarray
        Original data grid for residuals.
    s : float
        Target smoothing residual (`fp` target).
    fp0 : float or None
        Residual at `p = inf` (interpolatory limit,
                               represented by `p == -1`).
    p_init : float, optional
        Starting guess for the finite `p` search, default 1.0.
    tol_rel : float, optional
        Relative tolerance for matching `fp(p)` to `s`.
    maxit : int, optional
        Maximum iterations for the root search.

    Returns
    -------
    p_star : float
        Smoothing parameter for which `fp(p_star)` ~ `s`.
    C_star : ndarray
        Coefficient grid corresponding to `p_star`.
    fp_star : float
        Residual at `p_star`.

    Notes
    -----
    The solver treats `p == -1` as *p = inf* (interpolatory, no penalty).
    For finite `p`, the penalty scales as **1/p** - smaller `p` increases
    smoothing. A ratio-of-roots search (`root_rati`) iteratively adjusts `p`
    until the residual `fp(p)` matches the target `s` within tolerance.
    c                 ó   •—  ‰| «      ‰z
  S rB   r`   )rg   Úfp_atÚss    €€r3   Úgz_p_search_hit_s.<locals>.g¡  s   ø€ Ù�Q‹x˜!‰|Ðr5   r   r   gê-�™—q=)r—   )r�   r   ÚinfÚmaxr   Úrootr‰   )rt   r|   ru   r}   rv   r<   rw   rx   r=   ry   rz   r{   r›   Úfp0r•   r–   r—   rœ   ÚfpmsÚbracketÚftolÚrÚp_starÚfp_starÚC_starrš   s               `            @r3   Ú_p_search_hit_sr¨   h  s�   ù€ ôl ˆb�"�b˜"˜a Ø�#�r˜2˜s Aó'€Eõñ ˆR‹5€Dà�S˜1‘Wˆ~¤§¡¨˜~Ð.€GÜˆq�7‰{˜EÓ"€Dä�!�V˜W d°%Ô8€AØ�V‰V€FÙ�F‹m€GØ�W‰W€Fà�6˜7Ð"Ð"r5   c                 ó  — t        |D �cg c]  }|du ‘Œ c}«      r| ||t        d«      t        d«      fS |\  }}}}||k  r||k  st        d«      ‚t        j                  | |k\  | |k  z  «      d   }	t        j                  ||k\  ||k  z  «      d   }
|	j
                  dk(  s|
j
                  dk(  rt        d«      ‚| |	   ||
   |t        j                  |	|
«         t        j                  |	   t        j                  |
   fS c c}w )al  
    Restrict (x, y, Z) to a rectangular bounding box.

    Parameters
    ----------
    x, y : ndarray
        Monotonic sample coordinates.
    Z : ndarray, shape (len(x), len(y))
        Data grid.
    bbox : sequence of 4 scalars or None
        ``(xb, xe, yb, ye)``; any element may be None to skip clipping.

    Returns
    -------
    x_fit, y_fit, Z_fit : ndarray
        Sliced arrays restricted to bbox.
    ix, iy : slice or ndarray
        Indexers mapping from full arrays to the restricted ones.

    Raises
    ------
    ValueError
        If bbox is invalid or excludes all samples along an axis.
    Nz%bbox must satisfy xb < xe and yb < yer   z$bbox excludes all samples in x or y.)r#   Úslicer   r   Úwherer!   Úix_Ús_)r+   r,   ÚZÚbboxÚbboxiÚxbÚxeÚybÚyeÚixÚiys              r3   Ú_apply_bbox_gridr·   ±  sø   € ô2  tÖ,˜eˆE�TŠMÒ,Ô-Ø�!�Qœ˜d›¤U¨4£[Ð0Ð0à�N€BˆˆB�Ø�ŠG˜˜RšÜÐ@ÓAÐAä	�‰�1˜‘7˜q B™wÑ'Ó	(¨Ñ	+€BÜ	�‰�1˜‘7˜q B™wÑ'Ó	(¨Ñ	+€BØ	‡w�w�!‚|�r—w‘w !’|ÜÐ?Ó@Ð@àˆR‰5�!�B‘%˜œ2Ÿ6™6 " b›>Ñ*¬B¯E©E°"©I´r·u±u¸R±yÐ@Ð@ùò -s   ŠDc                 ó  — t        j                  | «      }t        j                  |«      }t        j                  | |||«      \  }	}
}t        j                  ||||«      \  }}}|j	                  «       }t        |	|
|«      t        |||«      |fS rB   )r   rl   r	   Údata_matrixrb   r@   )r+   r,   r{   rw   ry   r<   r=   r~   r   rt   Úoffset_xrƒ   ru   Úoffset_yr‡   rv   s                   r3   Ú_build_design_matricesr¼   Ù  s†   € ä
�,‰,�q‹/€CÜ
�,‰,�q‹/€Cä!×-Ñ-¨a°°R¸Ó=Ñ€Bˆ�$Ü!×-Ñ-¨a°°R¸Ó=Ñ€Bˆ�$Ø	�‰‹€Aä˜˜X tÓ,Ü˜˜X tÓ,Øðð r5   c                 óö   — |€t        | |z   dz   d|z  dz   «      }n#|d|dz   z  k  rt        d|›dd|dz   z  › d�«      ‚d|dz   z  }| |z   dz   }t        j                  |g|dz   z  |g|dz   z  z   «      }||||fS )ap  
    Initialize a non-periodic knot vector.

    Parameters
    ----------
    m : int
        Number of data points (equivalent to len(x) if x were provided).
    xb, xe : float
        Domain endpoints used to seed the initial knot vector with no internal knots.
    k : int
        Spline degree.
    nest : int, optional
        Storage cap for knots. If None, defaults to max(m + k + 1, 2*k + 3).
        Must satisfy nest >= 2*(k + 1); otherwise a ValueError is raised.

    Returns
    -------
    t : 1-D ndarray
        Initial knot vector with no internal knots: [xb]*(k+1) + [xe]*(k+1).
    nest : int
        The finalized storage cap for knots.
    nmin : int
        Lower bound on knot count.
    nmax : int
        Upper bound on knot count.

    What this does
    --------------
    - Computes defaults and bounds used by FITPACK-style knot growth:
        * nest: storage cap for knots (defaults to max(m + k + 1, 2*k + 3))
        * nmin: minimal knot count (2*(k+1))
        * nmax: maximal knot count (m + k + 1)
    - Returns an initial knot vector with no internal knots:
        t = [xb]*(k+1) + [xe]*(k+1)
    r   r   é   z`nest` too small: nest = z < 2*(k+1) = ú.)rž   r   r   r    )rU   r±   r²   rT   ÚnestÚnminÚnmaxr   s           r3   Ú_initialise_knotsrÃ   ç  s¬   € ðH €|Ü�1�q‘5˜1‘9˜a ™c A™gÓ&‰à�!�Q˜‘U‘)ÒÜÐ9°$°¸-ÈÈ1ÈQÉ3ÉÀyÐPQÐRÓSÐSàˆa�!‰e‰9€DØˆq‰5�1‰9€Dô 	�
‰
�B�4˜˜1™‘:   a¨¡c¡
Ñ*Ó+€Aàˆd�D˜$ÐÐr5   c                 ób  — |t         z  }|j                  }||z
  }||k(  rd}
n=||z
  }||kD  rt        |
|z  |z  «      n|
dz  }t        |
dz  t	        ||
dz  d«      «      }
t        |
«      D ]?  }t        | |||	«      }|j                  d   }||k\  rt        | |«      |
fc S ||k\  sŒ;||
fc S  ||
fS )aQ  
    Knot-growth helper for knot-finding loop (non-periodic).

    Parameters
    ----------
    x : 1-D ndarray
        Strictly increasing sample coordinates.
    k : int
        Spline degree.
    s : float
        Target smoothing.
    t : 1-D ndarray
        Current knot vector to be grown.
    nmin, nmax : int
        Lower/upper bounds on knot count (from initialisation).
    nest : int
        Storage cap for total knots.
    fp, fpold : float
        Current and previous residual sums of squares. Used to update nplus.
    residuals : 1-D ndarray
        Most recent residual signal used by `add_knot` to decide placement.
    nplus : int
        Previous iteration's proposed number of knots; used to update the next nplus.

    Returns
    -------
    t_new, nplus : tuple
        Updated knot vector and the nplus chosen for this step.
        If n >= nmax, t_new is a not-a-knot layout. If n >= nest, t_new is the
        current vector respecting the storage cap.

    What this function does
    -----------------------
    - Assumes the caller has already decided to GROW (i.e., checks
      like |fp - s| < acc or fp < s has FAILED).
    - Updates nplus (how many knots to add next) using the FITPACK heuristic
      based on the previous improvement (delta = fpold - fp).
    - Inserts up to nplus new internal knots using `add_knot(x, t, k, residuals)`.
    - Stops early if storage or interpolation caps are reached:
        * if n >= nmax: switch to interpolation layout (not-a-knot) and return
        * if n >= nest: return current t respecting storage cap

    How it compares with _fitpack_repro.py::_generate_knots_impl
    -------------------------------------------------------------
    Similarities:
      1) Same growth logic for nplus:
         - Use delta = fpold - fp with ratio fpms/delta
         - Apply min/max caps (doubling and halving behavior)
      3) Same storage guard:
         - If n reaches nest, stop and return current t
      4) Same end behavior at the "interpolating" cap:
         - When n >= nmax, switch to not-a-knot layout and return

    Differences:
      1) API style:
         - _generate_knots_impl is a generator that yields trial knot vectors and
           recomputes residuals/fp internally on each iteration.
         - `_add_knots` is a stateful helper that only grows knots; it expects the
           caller to handle residual computation and fp/fpold updates between calls.
      2) Periodicity:
         - _generate_knots_impl supports periodic=True.
         - `_add_knots` is non-periodic only; it uses not-a-knot when n >= nmax.
      3) Residual computation:
         - _generate_knots_impl calls an internal residual routine each iteration.
         - `_add_knots` does not compute residuals; the caller must supply:
             residuals (used by add_knot), fp, fpold.
      4) Return values:
         - _generate_knots_impl yields multiple t's and eventually returns None.
         - `_add_knots` returns:
             * (t_new, nplus) after inserting knots,
             * (not_a_knot_t, nplus) if n >= nmax,
             * (t, nplus) if n >= nest (storage cap).
    r   r   r   )	ÚTOLr!   ÚintrK   rž   rJ   r   r   r   )r+   rT   r›   r   rÁ   rÂ   rÀ   r7   ÚfpoldÚ	residualsÚnplusÚaccÚnr¡   ÚdeltaÚnpl1Újs                    r3   Ú
_add_knotsrÏ     sá   € ðZ Œc‰'€CØ	�‰€AØ�‰6€Dð 	ˆD‚yØ‰à˜‘
ˆØ,1°CªKŒs�5˜4‘< %Ñ'Ô(¸UÀ1¹WˆÜ�E˜!‘GœS  u¨a¡x°Ó3Ó4ˆô
 �5‹\ò ˆÜ�Q˜˜1˜iÓ(ˆð �G‰G�A‰Jˆð �Š9ô ˜q !Ó$ eÐ+Ò+ð �‹9Ø�e�8ŠOð'ð* ˆeˆ8€Or5   r¾   r   é2   ©r<   r=   r›   r—   ÚnestxÚnestyr¯   c                óz  — t        | |||	«      \  }
}}}}|
j                  |dz   k  s|j                  |dz   k  r8t        d|› d|› d|dz   › d|dz   › d|
j                  › d|j                  › d�«      ‚t        |	d   €|
d   n|	d   «      }t        |	d   €|
d
   n|	d   «      }t        |	d   €|d   n|	d   «      }t        |	d   €|d
   n|	d   «      }d
}|dk(  rg|€|�t        d«      ‚t	        |
|«      }t	        ||«      }t        |
||||||«      \  }}}t        |||||||
||||«      \  }}}t        ||||f||f«      S t        |
j                  ||||¬«      \  }}}}t        |j                  ||||¬«      \  }}}}d	}d}t        | «      t        |«      z   } d	}!d	}"d	}#t        | «      D ]á  }t        |
||||||«      \  }}}t        |||||||
||||«      \  }}}$t        |«      |k(  rt        |«      |k(  r|}!||k  r nŽ|dk(  r4t        |
||||||||t        j                  |$dz  d¬«      |"¬«      \  }}"d}n3t        |||||||||t        j                  |$dz  d¬«      |#¬«      \  }}#d}t        |«      |k\  rt        |«      |k\  r n|}Œã t        |«      |k(  r t        |«      |k(  rt        ||f||f«      S d}t        ||«      \  }%}&}'t        ||«      \  }(})}*t        |%|&|'«      }%t        |(|)|*«      }(t        |
||||||«      \  }}}t!        ||%||(||||
||||||!||¬«      \  }}+},t        |,|||+f||f«      S )a_  
    Core adaptive bivariate spline fitter using the 1/p-penalty convention.

    Parameters
    ----------
    x, y : array_like
        Strictly increasing coordinate vectors.
    Z : array_like, shape (len(x), len(y))
        Data grid.
    kx, ky : int, optional
        Spline degrees along x and y, default 3 (cubic).
    s : float, optional
        Target residual (`fp` target). `s = 0` requests an interpolatory
        surface; `s > 0` triggers smoothing with penalty weight **1/p**.
    maxit : int, optional
        Maximum iterations for the `p`-search when smoothing, default 50.
    nestx, nesty : int or None
        Max coefficient counts per axis (nesting limits).
    bbox : sequence of 4 scalars
        Optional domain limits `(xb, xe, yb, ye)`. Use `None` entries to skip.

    Returns
    -------
    NdBSpline
        Fitted 2-D spline surface.

    Notes
    -----
    The internal smoothing parameter `p` follows the **inverse**-penalty
    rule: penalty term is 1/p.  Hence, larger `p` -> weaker smoothing
    (approaching interpolation), while smaller `p` -> stronger smoothing.
    A sentinel value `p == -1` is interpreted as *p = inf*, corresponding to
    an exact (interpolatory) fit.

    The iterative process adaptively grows knot vectors based on residual
    energy and optionally performs a 1-D search over `p` to satisfy `fp ~ s`.
    r   z/Not enough samples inside bbox for degrees (kx=z, ky=z ). Need at least k+1 per axis: (z, z). Got (z).r   Nr   r   r¾   r   zs == 0 is interpolation only)rÀ   r,   r   )rÁ   rÂ   rÀ   r7   rÇ   rÈ   rÉ   r+   )r—   r•   )r·   r!   r   rc   r   r¼   rŽ   r>   rÃ   r   rJ   rÏ   r   rr   r   r@   r¨   )-r+   r,   r®   r<   r=   r›   r—   rÒ   rÓ   r¯   Úx_fitÚy_fitÚZ_fitrˆ   r±   r²   r³   r´   rg   rw   ry   rt   ru   rv   ÚC0r7   ÚnminxÚnmaxxÚnminyÚnmaxyrÇ   Ú	last_axisÚmpmr    ÚnplusxÚnplusyr�   ÚDrxÚ	offset_dxÚnc_dxÚDryÚ	offset_dyÚnc_dyÚC_smÚfp_sms-                                                r3   Ú_regrid_fitpackré   “  s  € ôR !1°°A°q¸$Ó ?Ñ€Eˆ5�%˜˜Aà‡z�z�R˜!‘VÒ §
¡
¨b°1©fÒ 5ÜØ=¸b¸TÀÀrÀdð K,Ø,.¨q©D¨6°°B°q±D°6ð :Ø—J‘J�<˜r %§*¡* ¨Rð1ó
ð 	
ô 
˜4 ™7˜?ˆu�QŠx°°Q±Ó	8€BÜ	˜D ™G˜Oˆu�RŠy°°a±Ó	9€BÜ	˜4 ™7˜?ˆu�QŠx°°Q±Ó	8€BÜ	˜D ™G˜Oˆu�RŠy°°a±Ó	9€Bà
€AàˆC‚xØÐ Ð 1ÜÐ;Ó<Ð<ô ˜ Ó#ˆÜ˜ Ó#ˆÜ,Ø�E˜1˜b " b¨"ó.‰ˆˆR�ä% b¨"¨a°Ø%'¨¨U°B¸Ø%*¨Eó3‰	ˆˆB�ô    R¨¨R L°2°r°(Ó;Ð;ä/°·
±
¸BÀÀBÈUÔSÑ€Bˆˆu�eÜ/°·
±
¸BÀÀBÈUÔSÑ€Bˆˆu�eà€EØ€IÜ
ˆa‹&”3�q“6‰/€CØ
€CØ€FØ€Fô �3‹Zò )ˆä,Ø�E˜1˜b " b¨"ó.‰ˆˆR�ô
 & b¨"¨a°Ø&(¨"¨eØ&(¨"¨eØ&+ó-‰	ˆˆB�ô ˆr‹7�eÒ¤ B£¨5Ò 0ØˆCà�Š6Ùð ˜ÒÜ#Ø�r˜1˜b u°5Ø˜r¨ÜŸ&™&  A¡¨AÔ.Øô	‰JˆB�ð
 ‰Iä#Ø�r˜1˜b u°5Ø˜r¨ÜŸ&™&  A¡¨AÔ.Øô	‰JˆB�ð
 ˆIô ˆr‹7�eÒ¤ B£¨5Ò 0Ùà‰ðS)ôV ˆ2ƒw�%ÒœC ›G uÒ,Ü  R¨¨R L°2°r°(Ó;Ð;à	€AÜ   R›LÑ€Cˆ�EÜ   R›LÑ€Cˆ�EÜ
�s˜I uÓ
-€CÜ
�s˜I uÓ
-€CÜ(Øˆu�a˜˜R  Ró)�K€RˆˆQä$ R¨¨b°#°qØ%'¨¨U°BØ%'¨°°qØ%(°¸aôA�N€A€tˆUô ˜E B¨¨D >°B¸°8Ó<Ð<r5   )r¯   r<   r=   r›   r—   c                ó   — |€dgdz  }t        j                  | t        ¬«      } t        j                  |t        ¬«      }t        j                  |t        ¬«      }t        j                  |«      }t        |«      }t        j                  t        j
                  | «      dkD  «      st        d«      ‚t        j                  t        j
                  |«      dkD  «      st        d«      ‚| j                  |j                  d   k7  rt        d«      ‚|j                  |j                  d	   k7  rt        d
«      ‚|dk  rt        d«      ‚|j                  dk(  st        d|j                  › �«      ‚t        | ||||||dd|¬«
      S )aÂ  
    Interface for 2-D smoothing B-spline fitting (1/p penalty form).

    Parameters
    ----------
    x, y : array_like
        Strictly increasing 1-D coordinate vectors.
    z : array_like, shape (len(x), len(y))
        Data grid.
    bbox : sequence of 4 scalars
        Optional bounding box ``(xb, xe, yb, ye)``; use ``None`` entries to disable.
    kx, ky : int, optional
        Spline degrees along `x` and `y`, default cubic (3).
    s : float, optional
        Target smoothing residual (`fp` target). Must satisfy ``s >= 0``.
        The underlying formulation uses a **1/p** penalty, meaning:
        - small `p` -> heavy smoothing,
        - large `p` -> light smoothing (approaching interpolation).
        Setting `p == -1` internally denotes *p = inf*, i.e. a pure interpolant.
    maxit : int, optional
        Maximum iterations for `p`-search if invoked.

    Returns
    -------
    NdBSpline
        Fitted bivariate spline surface.
    Né   r   r   zx must be strictly increasingzy must be strictly increasingr   z7x dimension of z must have same number of elements as xr   z7y dimension of z must have same number of elements as yzs should be s >= 0.0)rë   z"bbox shape should be (4,), found: rÑ   )
r   r    rc   r(   r#   r$   r   r!   r   ré   )r+   r,   r{   r¯   r<   r=   r›   r—   s           r3   Ú_regridrì   !  s=  € ð8 €|Øˆv�a‰xˆä
�
‰
�1œEÔ"€AÜ
�
‰
�1œEÔ"€AÜ
�
‰
�1œEÔ"€AÜ�8‰8�D‹>€DÜˆa‹€Aä�6‰6”"—'‘'˜!“*˜sÑ"Ô#ÜÐ8Ó9Ð9Ü�6‰6”"—'‘'˜!“*˜sÑ"Ô#ÜÐ8Ó9Ð9Ø‡v�v�—‘˜‘ÒÜÐRÓSÐSØ‡v�v�—‘˜‘ÒÜÐRÓSÐSØ	ˆCŠÜÐ/Ó0Ð0Ø�:‰:˜ÒÜÐ=¸d¿j¹j¸\ÐJÓKÐKäØ	ˆ1ˆa�B˜2 ¨%Ø˜$ Tô+ð +r5   )r   r   T)NNrB   )r^   Únumpyr   Úscipy.interpolate._ndbspliner   Ú scipy.interpolate._fitpack_repror   r   r   r   Ú r	   Úscipy.sparser
   Úscipy._lib._utilr   r4   r>   r@   rj   rŽ   r�   r¨   r·   r¼   rÃ   rÅ   rÏ   ré   rì   r`   r5   r3   ú<module>ró      s·   ðñTój Ý 2÷,ó ,å Ý "Ý *óG0òT3÷<)ñ )òX&ðV #'óJ÷X?ñ ?ðJ ˜ BôF#òR%AòPó0ðf €òtðp ˜˜cØ
�D Ø	ôK=ð\ " a¨A°¸Bõ 4+r5   