
    `ip:                    &   d dl Z d dlZd dlmZ d dlmZ d dlmZ d dl	m
Z
mZ d dlZ	 d dl mZ eZn# e$ r d ZY nw xY wdZd	d
gZddgZdZ ej        edddg          ZdZ ej        edd eD             d eD             z   d eD             z   d eD             z             ZdZ ej        edd eD                       Zd Zd Zd Zd Zd Zd Z d(dZ! G d  d!          Z" G d" d#e"          Z# G d$ d%e"          Z$ G d& d'          Z%dS ))    N)internal)get_typename)special)BSpline
_get_dtype)combc                     t          j        |           t          j        | |z
            t          j        |          z  z  S N)math	factorial)nks     x/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/cupyx/scipy/interpolate/_interpolate.py_combr      s4    ~a  T^AE%:%:T^A=N=N%NOO    @   doublezthrust::complex<double>intz	long longa2
  
#include <cupy/complex.cuh>

#define le_or_ge(x, y, r) ((r) ? ((x) < (y)) : ((x) > (y)))
#define ge_or_le(x, y, r) ((r) ? ((x) > (y)) : ((x) < (y)))
#define geq_or_leq(x, y, r) ((r) ? ((x) >= (y)) : ((x) <= (y)))

__device__ long long find_breakpoint_position(
        const double* breakpoints, const double xp, bool extrapolate,
        const int total_breakpoints, const bool* pasc) {

    double a = *&breakpoints[0];
    double b = *&breakpoints[total_breakpoints - 1];
    bool asc = pasc[0];

    if(isnan(xp)) {
        return -1;
    }

    if(le_or_ge(xp, a, asc) || ge_or_le(xp, b, asc)) {
        if(!extrapolate) {
            return -1;
        } else if(le_or_ge(xp, a, asc)) {
            return 0;
        } else {  // ge_or_le(xp, b, asc)
            return total_breakpoints - 2;
        }
    } else if (xp == b) {
        return total_breakpoints - 2;
    }

    int left = 0;
    int right = total_breakpoints - 2;
    int mid;

    if(le_or_ge(xp, *&breakpoints[left + 1], asc)) {
        right = left;
    }

    bool found = false;

    while(left < right && !found) {
        mid = ((right + left) / 2);
        if(le_or_ge(xp, *&breakpoints[mid], asc)) {
            right = mid;
        } else if (geq_or_leq(xp, *&breakpoints[mid + 1], asc)) {
            left = mid + 1;
        } else {
            found = true;
            left = mid;
        }
    }

    return left;

}

__global__ void find_breakpoint_position_1d(
        const double* breakpoints, const double* x, long long* out,
        bool extrapolate, int total_x, int total_breakpoints,
        const bool* pasc) {

    int idx = blockDim.x * blockIdx.x + threadIdx.x;
    if(idx >= total_x) {
        return;
    }

    const double xp = *&x[idx];
    out[idx] = find_breakpoint_position(
        breakpoints, xp, extrapolate, total_breakpoints, pasc);
}

__global__ void find_breakpoint_position_nd(
        const double* breakpoints, const double* x, long long* out,
        bool extrapolate, int total_x, const long long* x_dims,
        const long long* breakpoints_sizes,
        const long long* breakpoints_strides) {

    int idx = blockDim.x * blockIdx.x + threadIdx.x;
    if(idx >= total_x) {
        return;
    }

    const long long x_dim = *&x_dims[idx];
    const long long stride = breakpoints_strides[x_dim];
    const double* dim_breakpoints = breakpoints + stride;
    const int num_breakpoints = *&breakpoints_sizes[x_dim];

    const bool asc = true;
    const double xp = *&x[idx];
    out[idx] = find_breakpoint_position(
        dim_breakpoints, xp, extrapolate, num_breakpoints, &asc);
}
)z
-std=c++11find_breakpoint_position_1dfind_breakpoint_position_nd)codeoptionsname_expressionsa  
#include <cupy/complex.cuh>
#include <cupy/math_constants.h>

template<typename T>
__device__ T eval_poly_1(
        const double s, const T* coef, long long ci, int cj, int dx,
        const long long* c_dims, const long long stride_0,
        const long long stride_1) {
    int kp, k;
    T res, z;
    double prefactor;

    res = 0.0;
    z = 1.0;

    if(dx < 0) {
        for(int i = 0; i < -dx; i++) {
            z *= s;
        }
    }

    int c_dim_0 = (int) *&c_dims[0];

    for(kp = 0; kp < c_dim_0; kp++) {
        if(dx == 0) {
            prefactor = 1.0;
        } else if(dx > 0) {
            if(kp < dx) {
                continue;
            } else {
                prefactor = 1.0;
                for(k = kp; k > kp - dx; k--) {
                    prefactor *= k;
                }
            }
        } else {
            prefactor = 1.0;
            for(k = kp; k < kp - dx; k++) {
                prefactor /= k + 1;
            }
        }

        int off = stride_0 * (c_dim_0 - kp - 1) + stride_1 * ci + cj;
        T cur_coef = *&coef[off];
        res += cur_coef * z * ((T) prefactor);

        if((kp < c_dim_0 - 1) && kp >= dx) {
            z *= s;
        }

    }

    return res;

}

template<typename T>
__global__ void eval_ppoly(
        const T* coef, const double* breakpoints, const double* x,
        const long long* intervals, int dx, const long long* c_dims,
        const long long* c_strides, int num_x, T* out) {

    int idx = blockDim.x * blockIdx.x + threadIdx.x;

    if(idx >= num_x) {
        return;
    }

    double xp = *&x[idx];
    long long interval = *&intervals[idx];
    double breakpoint = *&breakpoints[interval];

    const int num_c = *&c_dims[2];
    const long long stride_0 = *&c_strides[0];
    const long long stride_1 = *&c_strides[1];

    if(interval < 0) {
        for(int j = 0; j < num_c; j++) {
            out[num_c * idx + j] = CUDART_NAN;
        }
        return;
    }

    for(int j = 0; j < num_c; j++) {
        T res = eval_poly_1<T>(
            xp - breakpoint, coef, interval, ((long long) (j)), dx,
            c_dims, stride_0, stride_1);
        out[num_c * idx + j] = res;
    }
}

template<typename T>
__global__ void eval_ppoly_nd(
        const T* coef, const double* xs, const double* xp,
        const long long* intervals, const long long* dx,
        const long long* ks, T* c2_all, const long long* c_dims,
        const long long* c_strides, const long long* xs_strides,
        const long long* xs_offsets, const long long* ks_strides,
        const int num_x, const int ndims, const int num_ks, T* out) {

    int idx = blockDim.x * blockIdx.x + threadIdx.x;
    if(idx >= num_x) {
        return;
    }

    const long long c_dim0 = c_dims[0];
    const int num_c = *&c_dims[2];
    const long long c_stride0 = c_strides[0];
    const long long c_stride1 = c_strides[1];

    const double* xp_dims = xp + ndims * idx;
    const long long* xp_intervals = intervals + ndims * idx;
    T* c2 = c2_all + c_dim0 * idx;

    bool invalid = false;
    for(int i = 0; i < ndims && !invalid; i++) {
        invalid = xp_intervals[i] < 0;
    }

    if(invalid) {
        for(int j = 0; j < num_c; j++) {
            out[num_c * idx + j] = CUDART_NAN;
        }
        return;
    }

    long long pos = 0;
    for(int k = 0; k < ndims; k++) {
        pos += xp_intervals[k] * xs_strides[k];
    }

    for(int jp = 0; jp < num_c; jp++) {
        for(int i = 0; i < c_dim0; i++) {
            c2[i] = coef[c_stride0 * i + c_stride1 * pos + jp];
        }

        for(int k = ndims - 1; k >= 0; k--) {
            const long long interval = xp_intervals[k];
            const long long xs_offset = xs_offsets[k];
            const double* dim_breakpoints = xs + xs_offset;
            const double xval = xp_dims[k] - dim_breakpoints[interval];

            const long long k_off = ks_strides[k];
            const long long dim_ks = ks[k];
            int kpos = 0;

            for(int ko = 0; ko < k_off; ko++) {
                const T* c2_off = c2 + kpos;
                const int k_dx = dx[k];
                T res = eval_poly_1<T>(
                    xval, c2_off, ((long long) 0), 0, k_dx,
                    &dim_ks, ((long long) 1), ((long long) 1));
                c2[ko] = res;
                kpos += dim_ks;
            }
        }

        out[num_c * idx + jp] =  c2[0];
    }
}

template<typename T>
__global__ void fix_continuity(
        T* coef, const double* breakpoints, const int order,
        const long long* c_dims, const long long* c_strides,
        int num_breakpoints) {

    const long long c_size0 = *&c_dims[0];
    const long long c_size2 = *&c_dims[2];
    const long long stride_0 = *&c_strides[0];
    const long long stride_1 = *&c_strides[1];
    const long long stride_2 = *&c_strides[2];

    for(int idx = 1; idx < num_breakpoints - 1; idx++) {
        const double breakpoint = *&breakpoints[idx];
        const long long interval = idx - 1;
        const double breakpoint_interval = *&breakpoints[interval];

        for(int jp = 0; jp < c_size2; jp++) {
            for(int dx = order; dx > -1; dx--) {
                T res = eval_poly_1<T>(
                    breakpoint - breakpoint_interval, coef,
                    interval, jp, dx, c_dims, stride_0, stride_1);

                for(int kp = 0; kp < dx; kp++) {
                    res /= kp + 1;
                }

                const long long c_idx = (
                    stride_0 * (c_size0 - dx - 1) + stride_1 * idx +
                    stride_2 * jp);

                coef[c_idx] = res;
            }
        }
    }
}

template<typename T>
__global__ void integrate(
        const T* coef, const double* breakpoints,
        const double* a_val, const double* b_val,
        const long long* start, const long long* end,
        const long long* c_dims, const long long* c_strides,
        const bool* pasc, T* out) {

    int idx = blockDim.x * blockIdx.x + threadIdx.x;
    const long long c_dim2 = *&c_dims[2];

    if(idx >= c_dim2) {
        return;
    }

    const bool asc = pasc[0];
    const long long start_interval = asc ? *&start[0] : *&end[0];
    const long long end_interval = asc ? *&end[0] : *&start[0];
    const double a = asc ? *&a_val[0] : *&b_val[0];
    const double b = asc ? *&b_val[0] : *&a_val[0];

    const long long stride_0 = *&c_strides[0];
    const long long stride_1 = *&c_strides[1];

    if(start_interval < 0 || end_interval < 0) {
        out[idx] = CUDART_NAN;
        return;
    }

    T vtot = 0;
    T vb;
    T va;
    for(int interval = start_interval; interval <= end_interval; interval++) {
        const double breakpoint = *&breakpoints[interval];
        if(interval == end_interval) {
            vb = eval_poly_1<T>(
                b - breakpoint, coef, interval, idx, -1, c_dims,
                stride_0, stride_1);
        } else {
            const double next_breakpoint = *&breakpoints[interval + 1];
            vb = eval_poly_1<T>(
                next_breakpoint - breakpoint, coef, interval,
                idx, -1, c_dims, stride_0, stride_1);
        }

        if(interval == start_interval) {
            va = eval_poly_1<T>(
                a - breakpoint, coef, interval, idx, -1, c_dims,
                stride_0, stride_1);
        } else {
            va = eval_poly_1<T>(
                0, coef, interval, idx, -1, c_dims,
                stride_0, stride_1);
        }

        vtot += (vb - va);
    }

    if(!asc) {
        vtot = -vtot;
    }

    out[idx] = vtot;

}
c                     g | ]}d | d	S )zeval_ppoly<> .0	type_names     r   
<listcomp>r      $    ;;;		#y	#	#	#;;;r   c                     g | ]}d | d	S )zeval_ppoly_nd<r   r   r   s     r   r    r      s$    >>>9	&)	&	&	&>>>r   c                     g | ]}d | d	S )zfix_continuity<r   r   r   s     r   r    r      s$    ???I	'9	'	'	'???r   c                     g | ]}d | d	S )z
integrate<r   r   r   s     r   r    r      s$    :::y	"i	"	"	":::r   a   
#include <cupy/complex.cuh>
#include <cupy/math_constants.h>

template<typename T>
__device__ T eval_bpoly1(
        const double s, const T* coef, const long long ci, const long long cj,
        const long long c_dims_0, const long long c_strides_0,
        const long long c_strides_1) {

    const long long k = c_dims_0 - 1;
    const double s1 = 1 - s;
    T res;

    const long long i0 = 0 * c_strides_0 + ci * c_strides_1 + cj;
    const long long i1 = 1 * c_strides_0 + ci * c_strides_1 + cj;
    const long long i2 = 2 * c_strides_0 + ci * c_strides_1 + cj;
    const long long i3 = 3 * c_strides_0 + ci * c_strides_1 + cj;

    if(k == 0) {
        res = coef[i0];
    } else if(k == 1) {
        res = coef[i0] * s1 + coef[i1] * s;
    } else if(k == 2) {
        res = coef[i0] * s1 * s1 + coef[i1] * 2.0 * s1 * s + coef[i2] * s * s;
    } else if(k == 3) {
        res = (coef[i0] * s1 * s1 * s1 + coef[i1] * 3.0 * s1 * s1 * s +
               coef[i2] * 3.0 * s1 * s * s + coef[i3] * s * s * s);
    } else {
        T comb = 1;
        res = 0;
        for(int j = 0; j < k + 1; j++) {
            const long long idx = j * c_strides_0 + ci * c_strides_1 + cj;
            res += (comb * pow(s, ((double) j)) * pow(s1, ((double) k) - j) *
                    coef[idx]);
            comb *= 1.0 * (k - j) / (j + 1.0);
        }
    }

    return res;
}

template<typename T>
__device__ T eval_bpoly1_deriv(
        const double s, const T* coef, const long long ci, const long long cj,
        int dx, T* wrk, const long long c_dims_0, const long long c_strides_0,
        const long long c_strides_1, const long long wrk_dims_0,
        const long long wrk_strides_0, const long long wrk_strides_1) {

    T res, term;
    double comb, poch;

    const long long k = c_dims_0 - 1;

    if(dx == 0) {
        res = eval_bpoly1<T>(s, coef, ci, cj, c_dims_0, c_strides_0,
                             c_strides_1);
    } else {
        poch = 1.0;
        for(int a = 0; a < dx; a++) {
            poch *= k - a;
        }

        term = 0;
        for(int a = 0; a < k - dx + 1; a++) {
            term = 0;
            comb = 1;
            for(int j = 0; j < dx + 1; j++) {
                const long long idx = (c_strides_0 * (j + a) +
                                       c_strides_1 * ci + cj);
                term += coef[idx] * pow(-1.0, ((double) (j + dx))) * comb;
                comb *= 1.0 * (dx - j) / (j + 1);
            }
            wrk[a] = term * poch;
        }

        res = eval_bpoly1<T>(s, wrk, 0, 0, wrk_dims_0, wrk_strides_0,
                             wrk_strides_1);
    }
    return res;
}

template<typename T>
__global__ void eval_bpoly(
        const T* coef, const double* breakpoints, const double* x,
        const long long* intervals, int dx, T* wrk, const long long* c_dims,
        const long long* c_strides, const long long* wrk_dims,
        const long long* wrk_strides, int num_x, T* out) {

    int idx = blockDim.x * blockIdx.x + threadIdx.x;

    if(idx >= num_x) {
        return;
    }

    double xp = *&x[idx];
    long long interval = *&intervals[idx];
    const int num_c = *&c_dims[2];

    const long long c_dims_0 = *&c_dims[0];
    const long long c_strides_0 = *&c_strides[0];
    const long long c_strides_1 = *&c_strides[1];

    const long long wrk_dims_0 = *&wrk_dims[0];
    const long long wrk_strides_0 = *&wrk_strides[0];
    const long long wrk_strides_1 = *&wrk_strides[1];

    if(interval < 0) {
        for(int j = 0; j < num_c; j++) {
            out[num_c * idx + j] = CUDART_NAN;
        }
        return;
    }

    const double ds = breakpoints[interval + 1] - breakpoints[interval];
    const double ds_dx = pow(ds, ((double) dx));
    T* off_wrk = wrk + idx * (c_dims_0 - dx);

    for(int j = 0; j < num_c; j++) {
        T res;
        const double s = (xp - breakpoints[interval]) / ds;
        if(dx == 0) {
            res = eval_bpoly1<T>(
                s, coef, interval, ((long long) (j)), c_dims_0, c_strides_0,
                c_strides_1);
        } else {
            res = eval_bpoly1_deriv<T>(
                s, coef, interval, ((long long) (j)), dx,
                off_wrk, c_dims_0, c_strides_0, c_strides_1,
                wrk_dims_0, wrk_strides_0, wrk_strides_1) / ds_dx;
        }
        out[num_c * idx + j] = res;
    }

}
c                     g | ]}d | d	S )zeval_bpoly<r   r   r   s     r   r    r      r!   r   c                     d |D             }d                     |          }|r| d| dn|}|                     |          }|S )Nc                 6    g | ]}t          |j                  S r   )r   dtype)r   args     r   r    z$_get_module_func.<locals>.<listcomp>  s"    DDDs<	**DDDr   z, <r   )joinget_function)module	func_nametemplate_argsargs_dtypestemplatekernel_namekernels          r   _get_module_funcr4     s^    DDmDDDKyy%%H0=LY,,,,,,9K  --FMr   c                 b   |d         |d         k    }t          j        |j        t           j                  }t                              d          } ||j        d         dz   dz
  dz  fd|||||j        d         |j        d         |f           t          j        | j        t           j                  }	t          j        | j        t           j                  | j        z  }
t          t          d|           } ||j        d         dz   dz
  dz  fd| |||||	|
|j        d         |f	           d	S )
aM  
    Evaluate a piecewise polynomial.

    Parameters
    ----------
    c : ndarray, shape (k, m, n)
        Coefficients local polynomials of order `k-1` in `m` intervals.
        There are `n` polynomials in each interval.
        Coefficient of highest order-term comes first.
    x : ndarray, shape (m+1,)
        Breakpoints of polynomials.
    xp : ndarray, shape (r,)
        Points to evaluate the piecewise polynomial at.
    dx : int
        Order of derivative to evaluate.  The derivative is evaluated
        piecewise and may have discontinuities.
    extrapolate : bool
        Whether to extrapolate to out-of-bounds points based on first
        and last intervals, or to return NaNs.
    out : ndarray, shape (r, n)
        Value of each polynomial at each of the input points.
        This argument is modified in-place.
    r   r(   r         r8   
eval_ppolyN)cupyemptyshapeint64INTERVAL_MODULEr,   asarraystridesitemsizer4   PPOLY_MODULE)cxxpdxextrapolateout	ascending	intervalsinterval_kernelc_shape	c_stridesppoly_kernels               r   _ppoly_evaluaterQ   %  s9   2 "1I
284:666I%22%' 'OObhqkC'!+35vI{BHQK ! ! !
 l17$*555GQYdj999QZGI#L,BBLL28A;$q(S02FQIr7I(1+s$% % % % %r   c                    |j         d         }|j        }t          |          }	|j        }
t          j        d |D             t          j                  }t          j        |          }t          j        d|dd         f         }t          j        |         }|dz
  }t          j        |ddd                   }t          j        |ddd         df         }t          j	        |j         t          j                  }t          j
        |	t          j                  }t          j        t          j        |d          ||	f          }|                                }t                              d          } ||dz   dz
  dz  fd	||||||||f           t          j        | j         t          j                  }t          j        | j        t          j                  | j        z  }t          j        || j         d         z  ddft'          |                     }t          j        t          j        d|f                   }|dd         }t)          t*          d
|           } ||dz   dz
  dz  fd	| |||||||||||||	|
|f           dS )a/  
    Evaluate a piecewise tensor-product polynomial.

    Parameters
    ----------
    c : ndarray, shape (k_1*...*k_d, m_1*...*m_d, n)
        Coefficients local polynomials of order `k-1` in
        `m_1`, ..., `m_d` intervals. There are `n` polynomials
        in each interval.
    xs : d-tuple of ndarray of shape (m_d+1,) each
        Breakpoints of polynomials
    ks : ndarray of int, shape (d,)
        Orders of polynomials in each dimension
    xp : ndarray, shape (r, d)
        Points to evaluate the piecewise polynomial at.
    dx : ndarray of int, shape (d,)
        Orders of derivative to evaluate.  The derivative is evaluated
        piecewise and may have discontinuities.
    extrapolate : int, optional
        Whether to extrapolate to out-of-bounds points based on first
        and last intervals, or to return NaNs.
    out : ndarray, shape (r, n)
        Value of each polynomial at each of the input points.
        For points outside the span ``x[0] ... x[-1]``,
        ``nan`` is returned.
        This argument is modified in-place.
    r   c                     g | ]	}|j         
S r   sizer   rF   s     r   r    z%_ndppoly_evaluate.<locals>.<listcomp>s  s    000QV000r   r7   Nr6   r9   r   r8   r:   eval_ppoly_nd)r>   rU   lenr<   rA   r?   cumsumr_cumprodr=   arangebroadcast_toexpand_dimscopyr@   r,   rB   rC   zerosr   r4   rD   )rE   xsksrG   rH   rI   rJ   num_samplestotal_xpndimsnum_ksxs_sizes
xs_offsetsxs_completexs_sizes_m1
xs_stridesrL   dim_seqxp_dimsrM   rN   rO   c2
ks_stridesrP   s                            r   _ndppoly_evaluaterp   Q  s{   8 (1+KwHGGEWF |00R000
CCCHX&&JJssO+,J'"+KQ,Kk%1R%011JDDbD)1,-J 
284:666Ik%tz222G!$${E&:< <GllnnG &22%' 'OOhnq(S02F "ihh
45 5 5
 l17$*555GQYdj999QZGI	[171:-q!4JqMM	J	J	JB dgaen--JCRCJ#L/1EELL;$q(S02F["iRWZZ&' ' ' ' 'r   c                    t          j        | j        t           j                  }t          j        | j        t           j                  | j        z  }t          t          d|           } |dd| |||||j        d         f           dS )a  
    Make a piecewise polynomial continuously differentiable to given order.

    Parameters
    ----------
    c : ndarray, shape (k, m, n)
        Coefficients local polynomials of order `k-1` in `m` intervals.
        There are `n` polynomials in each interval.
        Coefficient of highest order-term comes first.

        Coefficients c[-order-1:] are modified in-place.
    x : ndarray, shape (m+1,)
        Breakpoints of polynomials
    order : int
        Order up to which enforce piecewise differentiability.
    r7   fix_continuityr9   r   N)r<   rA   r>   r?   rB   rC   r4   rD   )rE   rF   orderrN   rO   continuity_kernels         r   _fix_continuityrv     s    $ l17$*555GQYdj999QZGI(7GKKdD!UGY
CE E E E Er   c                    |d         |d         k    }t          j        |gt           j                  }t          j        |gt           j                  }t          j        |j        t           j                  }t          j        |j        t           j                  }t                              d          }	 |	|j        d         dz   dz
  dz  fd|||||j        d         |j        d         |f            |	|j        d         dz   dz
  dz  fd|||||j        d         |j        d         |f           t          j        | j        t           j                  }
t          j        | j        t           j                  | j	        z  }t          t          d|           } || j        d	         dz   dz
  dz  fd| ||||||
|||f
           d
S )a  
    Compute integral over a piecewise polynomial.

    Parameters
    ----------
    c : ndarray, shape (k, m, n)
        Coefficients local polynomials of order `k-1` in `m` intervals.
    x : ndarray, shape (m+1,)
        Breakpoints of polynomials
    a : double
        Start point of integration.
    b : double
        End point of integration.
    extrapolate : bool, optional
        Whether to extrapolate to out-of-bounds points based on first
        and last intervals, or to return NaNs.
    out : ndarray, shape (n,)
        Integral of the piecewise polynomial, assuming the polynomial
        is zero outside the range (x[0], x[-1]).
        This argument is modified in-place.
    r6   r   r7   r   r8   r9   r:   	integrate   N)r<   rA   float64r=   r>   r?   r@   r,   rB   rC   r4   rD   )rE   rF   abrI   rJ   rK   start_intervalend_intervalrM   rN   rO   
int_kernels                r   
_integrater     s   . "1IaS---AaS---AZtz:::N:agTZ888L%22%' 'OOagaj3&*s24f>;
AGAJ ! ! ! Oagaj3&*s24f<agaj!'!* ! ! !
 l17$*555GQYdj999QZGI!,Q??JJc!A%#-/1aNL'93 ! ! ! ! !r   c                    |d         |d         k    }t          j        |j        t           j                  }t                              d          } ||j        d         dz   dz
  dz  fd|||||j        d         |j        d         |f           t          j        | j        t           j                  }	t          j        | j        t           j                  | j        z  }
t          j        |j        d         | j        d         |z
  z  ddft          |                     }t          j        | j        d         |z
  ddgt           j                  }t          j        |j        t           j                  |j        z  }t          t          d|           } ||j        d         dz   dz
  dz  fd| ||||||	|
|||j        d         |f           d	S )
aM  
    Evaluate a Bernstein polynomial.

    Parameters
    ----------
    c : ndarray, shape (k, m, n)
        Coefficients local polynomials of order `k-1` in `m` intervals.
        There are `n` polynomials in each interval.
        Coefficient of highest order-term comes first.
    x : ndarray, shape (m+1,)
        Breakpoints of polynomials.
    xp : ndarray, shape (r,)
        Points to evaluate the piecewise polynomial at.
    dx : int
        Order of derivative to evaluate.  The derivative is evaluated
        piecewise and may have discontinuities.
    extrapolate : bool
        Whether to extrapolate to out-of-bounds points based on first
        and last intervals, or to return NaNs.
    out : ndarray, shape (r, n)
        Value of each polynomial at each of the input points.
        This argument is modified in-place.
    r6   r   r7   r   r8   r9   r:   
eval_bpolyN)r<   r=   r>   r?   r@   r,   rA   rB   rC   r   r4   BPOLY_MODULE)rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   wrk	wrk_shapewrk_stridesbpoly_kernels                  r   _bpoly_evaluater     s   2 "1I
284:666I%22%' 'OObhqkC'!+35vI{BHQK ! ! !
 l17$*555GQYdj999QZGI
*bhqkQWQZ"_5q!<%a==* * *Cagaj2oq!4DJGGGI,s{$*===MK#L,BBLL28A;$q(S02FQIr3Irx{C12 2 2 2 2r   c                    t          | t                    r-t          |           dk    rt          j        | d                   } t          | t                    r;t          j        d | D              }d |D             }t          j        |d          } nNt          j        |           } | j        dk    r/||                     dd          } n|                     d|          } | S )zM
    Convert a tuple of coordinate arrays to a (..., ndim)-shaped array.
    r9   r   c                 6    g | ]}t          j        |          S r   )r<   rA   rV   s     r   r    z,_ndim_coords_from_arrays.<locals>.<listcomp>   s     #D#D#DDLOO#D#D#Dr   c                 8    g | ]}t          j        |d           S )r6   )r<   r^   rV   s     r   r    z,_ndim_coords_from_arrays.<locals>.<listcomp>!  s%    000Ta$$000r   r6   axis)	
isinstancetuplerX   r<   rA   broadcast_arraysconcatenatendimreshape)pointsr   ps      r   _ndim_coords_from_arraysr     s    
 &%   )S[[A%5%5fQi((&%   
2!#D#DV#D#D#DE00a000!!"---f%%;!|A..D11Mr   c                   P    e Zd ZdZdZddZd Zedd            Zd Z	d	 Z
dd
ZdS )
_PPolyBasez%Base class for piecewise polynomials.)rE   rF   rI   r   Nr   c                    t          j        |          | _        t          j        |t           j                  | _        |d}n|dk    rt          |          }|| _        | j        j        dk     rt          d          d|cxk    r| j        j        dz
  k     s$n t          d|d	| j        j        dz
            || _
        |dk    rFt          j        | j        |dz   d          | _        t          j        | j        |dz   d          | _        | j        j        dk    rt          d
          | j        j        dk     rt          d          | j        j        dk     rt          d          | j        j        d         dk    rt          d          | j        j        d         | j        j        dz
  k    rt          d          t          j        | j                  }t          j        |dk              s't          j        |dk              st          d          |                     | j        j                  }t          j        | j        |          | _        d S )Nr7   Tperiodicry   z2Coefficients array must be at least 2-dimensional.r   r9   zaxis=z must be between 0 and zx must be 1-dimensionalz!at least 2 breakpoints are neededz!c must have at least 2 dimensionsz&polynomial must be at least of order 0z"number of coefficients != len(x)-1z.`x` must be strictly increasing or decreasing.)r<   rA   rE   ascontiguousarrayrz   rF   boolrI   r   
ValueErrorr   moveaxisrU   r>   diffallr   r(   )selfrE   rF   rI   r   rH   r(   s          r   __init__z_PPolyBase.__init__1  s;   a'>>>KKJ&&{++K&6;?? . / / / T++++DFK!O++++*"ddDFKMM3 4 4 4 	199 ]4646155DF]4646155DF6;!67776;??@AAA6;??@AAA6<?aEFFF6<?dfk!m++ABBBYtvq!! 	OTXbAg%6%6 	OMNNN--'e<<<r   c                     t          j        |t           j                  s)t          j        | j        j        t           j                  rt           j        S t           j        S r
   r<   
issubdtypecomplexfloatingrE   r(   
complex128rz   r   r(   s     r   r   z_PPolyBase._get_dtype_  D    OE4#788 	 ?46<1EFF	 ?"<r   c                 z    t                               |           }||_        ||_        ||_        |d}||_        |S )aG  
        Construct the piecewise polynomial without making checks.
        Takes the same parameters as the constructor. Input arguments
        ``c`` and ``x`` must be arrays of the correct shape and type. The
        ``c`` array can only be of dtypes float and complex, and ``x``
        array must have dtype float.
        NT)object__new__rE   rF   r   rI   )clsrE   rF   rI   r   r   s         r   construct_fastz_PPolyBase.construct_fastf  sB     ~~c""	K&r   c                     | j         j        j        s| j                                         | _         | j        j        j        s | j                                        | _        dS dS )zr
        c and x may be modified by the user. The Cython code expects
        that they are C contiguous.
        N)rF   flagsc_contiguousr_   rE   r   s    r   _ensure_c_contiguousz_PPolyBase._ensure_c_contiguousx  sR    
 v|( 	#V[[]]DFv|( 	#V[[]]DFFF	# 	#r   c                    t          j        |          }t          j        |          }|j        dk     rt          d          |j        dk    rt          d          |j        d         |j        d         k    r-t          d                    |j        |j                            |j        dd         | j        j        dd         k    s|j        | j        j        k    r2t          d                    |j        | j        j                            |j        dk    rdS t          j        |          }t          j	        |dk              s't          j	        |dk              st          d	          | j
        d
         | j
        d         k    rd|d
         |d         k    st          d          |d         | j
        d
         k    rd}n|d
         | j
        d         k    rd}nst          d          |d
         |d         k    st          d          |d         | j
        d
         k    rd}n)|d
         | j
        d         k    rd}nt          d          |                     |j                  }t          |j        d         | j        j        d                   }t          j        || j        j        d         |j        d         z   f| j        j        dd         z   |          }|dk    r{| j        ||| j        j        d         z
  dd| j        j        d         f<   ||||j        d         z
  d| j        j        d         df<   t           j        | j
        |f         | _
        nv|dk    rp|||| j        j        d         z
  dd|j        d         f<   | j        |||j        d         z
  d|j        d         df<   t           j        || j
        f         | _
        || _        dS )a#  
        Add additional breakpoints and coefficients to the polynomial.

        Parameters
        ----------
        c : ndarray, size (k, m, ...)
            Additional coefficients for polynomials in intervals. Note that
            the first additional interval will be formed using one of the
            ``self.x`` end points.
        x : ndarray, size (m,)
            Additional breakpoints. Must be sorted in the same order as
            ``self.x`` and either to the right or to the left of the current
            breakpoints.
        ry   zinvalid dimensions for cr9   zinvalid dimensions for xr   z(Shapes of x {} and c {} are incompatibleNz-Shapes of c {} and self.c {} are incompatiblez`x` is not sorted.r6   z,`x` is in the different order than `self.x`.appendprependz9`x` is neither on the left or on the right from `self.x`.r7   )r<   rA   r   r   r>   formatrE   rU   r   r   rF   r   r(   maxr`   rZ   )r   rE   rF   rH   actionr(   k2rn   s           r   extendz_PPolyBase.extend  s     LOOLOO6A::78886Q;;788871:##G$fQWag668 8 87122;$&,qrr***af.C.CL$fQWdfl;;= = = 6Q;;FYq\\q!! 	3TXbAg%6%6 	312226":""R5AaD==  "2 3 3 3 ttvbz!!!2$&)##"  "2 3 3 3 R5AaD==  "2 3 3 3 ttvbz!!!2$&)##"  "2 3 3 3 ((TV\!_--Za171:-.abb1AA   X:>&BrDFLO#$$&6tv|A&66756BrAGAJa!1!112WTVQY'DFFy  56BrDFLO#$$kqwqzk1204BrAGAJ,-WQY'DFr   c           
         || j         }t          j        |          }|j        |j        }}t          j        |                                t          j                  }|dk    r<| j        d         || j        d         z
  | j        d         | j        d         z
  z  z   }d}t          j	        t          |          t          t          j        | j        j        dd                             f| j        j                  }|                                  |                     ||||           |                    || j        j        dd         z             }| j        dk    rft)          t+          |j                            }|||| j        z            |d|         z   ||| j        z   d         z   }|                    |          }|S )aX  
        Evaluate the piecewise polynomial or its derivative.

        Parameters
        ----------
        x : array_like
            Points to evaluate the interpolant at.
        nu : int, optional
            Order of derivative to evaluate. Must be non-negative.
        extrapolate : {bool, 'periodic', None}, optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used.
            If None (default), use `self.extrapolate`.

        Returns
        -------
        y : array_like
            Interpolated values. Shape is determined by replacing
            the interpolation axis in the original array with the shape of x.

        Notes
        -----
        Derivatives are evaluated piecewise for each polynomial
        segment, even if the polynomial is not differentiable at the
        breakpoints. The polynomial intervals are considered half-open,
        ``[a, b)``, except for the last interval which is closed
        ``[a, b]``.
        Nr7   r   r   r6   Fry   )rI   r<   rA   r>   r   r   ravelrz   rF   r=   rX   r   npprodrE   r(   r   	_evaluater   r   listrange	transpose)r   rF   nurI   x_shapex_ndimrJ   dimss           r   __call__z_PPolyBase.__call__  s   < *KLOO'16"17799DLAAA *$$q	Q]tvbzDF1I/EFFAKj#a&&#bgdfl122.>&?&?"@"@A#v|- - -!!###q"k3///kk'DFL$44559>>ch((D 223d7F7mC$)+,,-.D--%%C
r   Nr   r   N)__name__
__module____qualname____doc__	__slots__r   r   classmethodr   r   r   r   r   r   r   r   r   -  s        //1I,= ,= ,= ,=\         ["# # #N N N`5 5 5 5 5 5r   r   c                   p    e Zd ZdZd ZddZddZddZdd
ZddZ	e
dd            Ze
dd            ZdS )PPolya  
    Piecewise polynomial in terms of coefficients and breakpoints
    The polynomial between ``x[i]`` and ``x[i + 1]`` is written in the
    local power basis::

        S = sum(c[m, i] * (xp - x[i]) ** (k - m) for m in range(k + 1))

    where ``k`` is the degree of the polynomial.

    Parameters
    ----------
    c : ndarray, shape (k, m, ...)
        Polynomial coefficients, order `k` and `m` intervals.
    x : ndarray, shape (m+1,)
        Polynomial breakpoints. Must be sorted in either increasing or
        decreasing order.
    extrapolate : bool or 'periodic', optional
        If bool, determines whether to extrapolate to out-of-bounds points
        based on first and last intervals, or to return NaNs. If 'periodic',
        periodic extrapolation is used. Default is True.
    axis : int, optional
        Interpolation axis. Default is zero.

    Attributes
    ----------
    x : ndarray
        Breakpoints.
    c : ndarray
        Coefficients of the polynomials. They are reshaped
        to a 3-D array with the last dimension representing
        the trailing dimensions of the original coefficient array.
    axis : int
        Interpolation axis.

    See also
    --------
    BPoly : piecewise polynomials in the Bernstein basis

    Notes
    -----
    High-order polynomials in the power basis can be numerically
    unstable. Precision problems can start to appear for orders
    larger than 20-30.

    .. seealso:: :class:`scipy.interpolate.BSpline`
    c           	          t          | j                            | j        j        d         | j        j        d         d          | j        ||t          |          |           d S )Nr   r9   r6   )rQ   rE   r   r>   rF   r   r   rF   r   rI   rJ   s        r   r   zPPoly._evaluate:  sW    tv|AQLL2tK'8'8#	? 	? 	? 	? 	?r   r9   c                 B   |dk     r|                      |           S |dk    r| j                                        }n&| j        d| ddf                                         }|j        d         dk    r+t	          j        d|j        dd         z   |j                  }t          j        t	          j	        |j        d         dd          |          }||t          d          fd|j        dz
  z  z            z  }|                     || j        | j        | j                  S )a  
        Construct a new piecewise polynomial representing the derivative.

        Parameters
        ----------
        nu : int, optional
            Order of derivative to evaluate. Default is 1, i.e., compute the
            first derivative. If negative, the antiderivative is returned.

        Returns
        -------
        pp : PPoly
            Piecewise polynomial of order k2 = k - n representing the
            derivative of this polynomial.

        Notes
        -----
        Derivatives are evaluated piecewise for each polynomial
        segment, even if the polynomial is not differentiable at the
        breakpoints. The polynomial intervals are considered half-open,
        ``[a, b)``, except for the last interval which is closed
        ``[a, b]``.
        r   Nrs   r9   r7   r6   r
   )antiderivativerE   r_   r>   r<   r`   r(   specpochr\   slicer   r   rF   rI   r   )r   r   rn   factors       r   
derivativezPPoly.derivative>  s   0 66&&s+++ 77BB"aaa%%''B8A;!D28ABB</rx@@@B 4;rx{Ar::B??
feDkk^grwqy&99:: ""2tvt/?KKKr   c                    |dk    r|                      |           S t          j        | j        j        d         |z   | j        j        d         f| j        j        dd         z   | j        j                  }| j        |d| <   t          j        t          j        | j        j        d         dd          |          }|d| xx         |t          d          fd|j
        dz
  z  z            z  cc<   |                                  t          |                    |j        d         |j        d         d          | j        |dz
             | j        dk    rd	}n| j        }|                     || j        || j                  S )
a<  
        Construct a new piecewise polynomial representing the antiderivative.
        Antiderivative is also the indefinite integral of the function,
        and derivative is its inverse operation.

        Parameters
        ----------
        nu : int, optional
            Order of antiderivative to evaluate. Default is 1, i.e., compute
            the first integral. If negative, the derivative is returned.

        Returns
        -------
        pp : PPoly
            Piecewise polynomial of order k2 = k + n representing
            the antiderivative of this polynomial.

        Notes
        -----
        The antiderivative returned by this function is continuous and
        continuously differentiable to order n-1, up to floating point
        rounding error.

        If antiderivative is computed and ``self.extrapolate='periodic'``,
        it will be set to False for the returned instance. This is done because
        the antiderivative is no longer periodic and its correct evaluation
        outside of the initially given x interval is difficult.
        r   r9   ry   Nr7   r6   r
   r   F)r   r<   r`   rE   r>   r(   r   r   r\   r   r   r   rv   r   rF   rI   r   r   )r   r   rE   r   rI   s        r   r   zPPoly.antiderivativej  sp   : 77??B3'''JV\!_r!46<?3dfl1226FF&,      &$B3$ 4;tv|A2>>CC	$B3$65;;.7afQh+??@@ 	!!###		!'!*agaj"==Q	( 	( 	( z))KK*K ""1dfk49EEEr   Nc           	         || j         }d}||k     r||}}d}t          j        t          t	          j        | j        j        dd                             f| j        j                  }| 	                                 |dk    r| j
        d         | j
        d         }}||z
  }||z
  }	t          |	|          \  }
}|
dk    rZt          | j                            | j        j        d         | j        j        d         d          | j
        ||d|	           ||
z  }n|                    d           |||z
  |z  z   }||z   }t          j        |          }||k    r[t          | j                            | j        j        d         | j        j        d         d          | j
        ||d|	           ||z  }nt          | j                            | j        j        d         | j        j        d         d          | j
        ||d|	           ||z  }t          | j                            | j        j        d         | j        j        d         d          | j
        |||z   |z   |z
  d|	           ||z  }nat          | j                            | j        j        d         | j        j        d         d          | j
        ||t!          |          |	           ||z  }|                    | j        j        dd                   S )
a  
        Compute a definite integral over a piecewise polynomial.

        Parameters
        ----------
        a : float
            Lower integration bound
        b : float
            Upper integration bound
        extrapolate : {bool, 'periodic', None}, optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used.
            If None (default), use `self.extrapolate`.

        Returns
        -------
        ig : array_like
            Definite integral of the piecewise polynomial over [a, b]
        Nr9   r6   ry   r7   r   r   F)rJ   )rI   r<   r=   r   r   r   rE   r>   r(   r   rF   divmodr   r   fill
empty_liker   )r   r{   r|   rI   sign	range_intra   xeperiodinterval	n_periodsleftremainder_ints                r   rx   zPPoly.integrate  s   * *K q55aqADJabb)**++-TV\C C C	!!### *$$ VAYr
B"WF1uH$Xv66OIt1}}FNN46<?DFLORHHFBEy: : : : Y&		q!!! a"f&&ADA !OI66MBwwFNN46<?DFLORHHFAq%]< < < < ]*		FNN46<?DFLORHHFAr5m= = = = ]*	FNN46<?DFLORHHFBT	A 2E}N N N N ]*		tv|AQDD1d;//Y@ @ @ @
 	T	  abb!1222r           Tc                      t          d          )a  
        Find real solutions of the equation ``pp(x) == y``.

        Parameters
        ----------
        y : float, optional
            Right-hand side. Default is zero.
        discontinuity : bool, optional
            Whether to report sign changes across discontinuities at
            breakpoints as roots.
        extrapolate : {bool, 'periodic', None}, optional
            If bool, determines whether to return roots from the polynomial
            extrapolated based on first and last intervals, 'periodic' works
            the same as False. If None (default), use `self.extrapolate`.

        Returns
        -------
        roots : ndarray
            Roots of the polynomial(s).
            If the PPoly object describes multiple polynomials, the
            return value is an object array whose each element is an
            ndarray containing the roots.

        Notes
        -----
        This routine works only on real-valued polynomials.
        If the piecewise polynomial contains sections that are
        identically zero, the root list will contain the start point
        of the corresponding interval, followed by a ``nan`` value.
        If the polynomial is discontinuous across a breakpoint, and
        there is a sign change across the breakpoint, this is reported
        if the `discont` parameter is True.

        At the moment, there is not an actual implementation.
        z9At the moment there is not a GPU implementation for solve)NotImplementedError)r   ydiscontinuityrI   s       r   solvezPPoly.solve  s    H "GI I 	Ir   c                 0    |                      d||          S )aZ  
        Find real roots of the piecewise polynomial.

        Parameters
        ----------
        discontinuity : bool, optional
            Whether to report sign changes across discontinuities at
            breakpoints as roots.
        extrapolate : {bool, 'periodic', None}, optional
            If bool, determines whether to return roots from the polynomial
            extrapolated based on first and last intervals, 'periodic' works
            the same as False. If None (default), use `self.extrapolate`.

        Returns
        -------
        roots : ndarray
            Roots of the polynomial(s).
            If the PPoly object describes multiple polynomials, the
            return value is an object array whose each element is an
            ndarray containing the roots.

        See Also
        --------
        PPoly.solve
        r   )r   )r   r   rI   s      r   rootszPPoly.roots  s    4 zz!]K888r   c                    t          |t                    r|j        \  }}}||j        }n|\  }}}t          ||||          }t	          j        |dz   t          |          dz
  f|j                  }t          |dd          D ];} ||dd         |          }	|	t          j
        |dz             z  |||z
  ddf<   <|                     |||          S )a  
        Construct a piecewise polynomial from a spline

        Parameters
        ----------
        tck
            A spline, as a (knots, coefficients, degree) tuple or
            a BSpline object.
        extrapolate : bool or 'periodic', optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used. Default is True.
        NrI   r9   r7   r6   )r   )r   r   tckrI   r<   r=   rX   r(   r   r   gammar   )
r   r   rI   trE   r   splcvalsmr   s
             r   from_splinezPPoly.from_spline6  s     c7## 	gGAq!"!oGAq!aA;777
AE3q66A:.ag>>>q"b!! 	4 	4AAcrcFq!!!A$*QU"3"33E!a%(OO!!%K888r   c           
         t          |t                    st          dt          |          z            t	          j        |j                  }|j        j        d         dz
  }d|j        j	        dz
  z  }t	          j
        |j                  }t          |dz             D ]}d|z  t          ||          z  |j        |         z  }t          ||dz             D ]Q}	t          ||z
  |	|z
            d|	z  z  }
|||	z
  xx         ||
z  |t          d          f|z            |	z  z  z  cc<   R||j        }|                     ||j        ||j                  S )a  
        Construct a piecewise polynomial in the power basis
        from a polynomial in Bernstein basis.

        Parameters
        ----------
        bp : BPoly
            A Bernstein basis polynomial, as created by BPoly
        extrapolate : bool or 'periodic', optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used. Default is True.
        zC.from_bernstein_basis only accepts BPoly instances. Got %s instead.r   r9   r
   ry   r6   N)r   BPoly	TypeErrortyper<   r   rF   rE   r>   r   
zeros_liker   r   r   rI   r   r   )r   bprI   rH   r   restrE   r{   r   svals              r   from_bernstein_basiszPPoly.from_bernstein_basisT  sl    "e$$ 	E 9;?88D E E E Yrt__DJqMA	!$OBD!!qs 	D 	DA1WuQ{{*RT!W4F1ac]] D DAaC1ooa/!A#&3,U4[[N4,?)@!)CCCD .K!!!RT;@@@r   rs   r
   )r   TN)TN)r   r   r   r   r   r   r   rx   r   r   r   r   r  r   r   r   r   r   
  s        - -^? ? ?*L *L *L *LX4F 4F 4F 4FlQ3 Q3 Q3 Q3f%I %I %I %IN9 9 9 98 9 9 9 [9: !A !A !A [!A !A !Ar   r   c                       e Zd ZdZd ZddZddZddZd Ze	j        j        e_        e
d	             Zedd
            Zedd            Ze
d             ZdS )r   a 	  
    Piecewise polynomial in terms of coefficients and breakpoints.

    The polynomial between ``x[i]`` and ``x[i + 1]`` is written in the

    Bernstein polynomial basis::

        S = sum(c[a, i] * b(a, k; x) for a in range(k+1)),

    where ``k`` is the degree of the polynomial, and::

        b(a, k; x) = binom(k, a) * t**a * (1 - t)**(k - a),

    with ``t = (x - x[i]) / (x[i+1] - x[i])`` and ``binom`` is the binomial
    coefficient.

    Parameters
    ----------
    c : ndarray, shape (k, m, ...)
        Polynomial coefficients, order `k` and `m` intervals
    x : ndarray, shape (m+1,)
        Polynomial breakpoints. Must be sorted in either increasing or
        decreasing order.
    extrapolate : bool, optional
        If bool, determines whether to extrapolate to out-of-bounds points
        based on first and last intervals, or to return NaNs. If 'periodic',
        periodic extrapolation is used. Default is True.
    axis : int, optional
        Interpolation axis. Default is zero.

    Attributes
    ----------
    x : ndarray
        Breakpoints.
    c : ndarray
        Coefficients of the polynomials. They are reshaped
        to a 3-D array with the last dimension representing
        the trailing dimensions of the original coefficient array.
    axis : int
        Interpolation axis.

    See also
    --------
    PPoly : piecewise polynomials in the power basis

    Notes
    -----
    Properties of Bernstein polynomials are well documented in the literature,
    see for example [1]_ [2]_ [3]_.

    References
    ----------
    .. [1] https://en.wikipedia.org/wiki/Bernstein_polynomial
    .. [2] Kenneth I. Joy, Bernstein polynomials,
       http://www.idav.ucdavis.edu/education/CAGDNotes/Bernstein-Polynomials.pdf
    .. [3] E. H. Doha, A. H. Bhrawy, and M. A. Saker, Boundary Value Problems,
           vol 2011, article ID 829546,
           `10.1155/2011/829543 <https://doi.org/10.1155/2011/829543>`_.

    Examples
    --------
    >>> from cupyx.scipy.interpolate import BPoly
    >>> x = [0, 1]
    >>> c = [[1], [2], [3]]
    >>> bp = BPoly(c, x)

    This creates a 2nd order polynomial

    .. math::

        B(x) = 1 \times b_{0, 2}(x) + 2 \times b_{1, 2}(x) +
               3 \times b_{2, 2}(x) \\
             = 1 \times (1-x)^2 + 2 \times 2 x (1 - x) + 3 \times x^2
    c           	          |dk     rt          d          t          | j                            | j        j        d         | j        j        d         d          | j        ||t          |          |           d S )Nr   z-Cannot do antiderivatives in the B-basis yet.r9   r6   )r   r   rE   r   r>   rF   r   r   s        r   r   zBPoly._evaluate  s{    66%?A A A 	FNN46<?DFLOR@@FAr4,,c	3 	3 	3 	3 	3r   r9   c                    |dk     r|                      |           S |dk    r*| }t          |          D ]}|                                }|S |dk    r| j                                        }nyd| j        j        dz
  z  }| j        j        d         dz
  }t          j        | j	                  dt          d          f|z            }|t          j        | j        d          z  |z  }|j        d         dk    r+t          j        d|j        dd         z   |j                  }|                     || j	        | j        | j                  S )	a  
        Construct a new piecewise polynomial representing the derivative.

        Parameters
        ----------
        nu : int, optional
            Order of derivative to evaluate. Default is 1, i.e., compute the
            first derivative. If negative, the antiderivative is returned.

        Returns
        -------
        bp : BPoly
            Piecewise polynomial of order k - nu representing the derivative of
            this polynomial.
        r   r9   r
   ry   Nr   rs   r7   )r   r   r   rE   r_   r   r>   r<   r   rF   r   r`   r(   r   rI   r   )r   r   r   r   rn   r   rH   s          r   r   zBPoly.derivative  s;     66&&s+++66B2YY % %]]__I 77BB dfk!m,DQ!#A46""D%++#6t#;<BTYtvA....3B8A;!D28ABB</rx@@@B ""2tvt/?KKKr   c           	         |dk    r|                      |           S |dk    r*| }t          |          D ]}|                                }|S | j        | j        }}|j        d         }t          j        |dz   f|j        dd         z   |j                  }t          j	        |d          |z  |dddf<   |dd         |dd         z
  }||dt          d          fd|j        d	z
  z  z            z  }|ddddfxx         t          j	        ||ddf         d          dd         z  cc<   | j        d
k    rd}n| j        }|                     |||| j                  S )a  
        Construct a new piecewise polynomial representing the antiderivative.

        Parameters
        ----------
        nu : int, optional
            Order of antiderivative to evaluate. Default is 1, i.e., compute
            the first integral. If negative, the derivative is returned.

        Returns
        -------
        bp : BPoly
            Piecewise polynomial of order k + nu representing the
            antiderivative of this polynomial.

        Notes
        -----
        If antiderivative is computed and ``self.extrapolate='periodic'``,
        it will be set to False for the returned instance. This is done because
        the antiderivative is no longer periodic and its correct evaluation
        outside of the initially given x interval is difficult.
        r   r9   Nr7   r   .r6   r
   ry   r   F)r   r   r   rE   rF   r>   r<   r`   r(   rY   r   r   rI   r   r   )	r   r   r   r   rE   rF   rn   deltarI   s	            r   r   zBPoly.antiderivative  s   . 77??B3'''66B2YY ) )&&((I vtv1GAJZ1,AG<<<k!!,,,q0122s7!""#2#
eT5;;''16!8*<<== 	111abb5			T[AqqqD2223B377			z))KK*K""2q+DI"FFFr   Nc                 2   |                                  }|| j        }|dk    r||_        |dk    r||k    rd}n||}}d}| j        d         | j        d         }}||z
  }||z
  }	t          |	|          \  }
}|
 ||           ||          z
  z  }|||z
  |z  z   }||z   }||k    r| ||           ||          z
  z  }n;| ||           ||          z
   |||z   |z   |z
            z    ||          z
  z  }||z  S  ||           ||          z
  S )as  
        Compute a definite integral over a piecewise polynomial.

        Parameters
        ----------
        a : float
            Lower integration bound
        b : float
            Upper integration bound
        extrapolate : {bool, 'periodic', None}, optional
            Whether to extrapolate to out-of-bounds points based on first
            and last intervals, or to return NaNs. If 'periodic', periodic
            extrapolation is used. If None (default), use `self.extrapolate`.

        Returns
        -------
        array_like
            Definite integral of the piecewise polynomial over [a, b]
        Nr   r9   r6   r   )r   rI   rF   r   )r   r{   r|   rI   ibr   ra   r   r   r   r   r   ress                r   rx   zBPoly.integrate=  sn   ,   ""*K *$$(BN*$$
 Avv!1VAYr
B"WF1uH$Xv66OItrr"vv2/C a"f&&ADA Bwwrr!uurr!uu}$rr"vv1~29q=2+=(>(>>BGG#:2a5522a55= r   c                 >   t          | j        j        d         |j        d                   }|                     | j        || j        j        d         z
            | _        |                     |||j        d         z
            }t                              | ||          S r   )r   rE   r>   _raise_degreer   r   )r   rE   rF   r   s       r   r   zBPoly.extend|  s|    Q,,##DFAQ,?@@q!agaj.11  q!,,,r   c                    |dk    r| S | j         d         dz
  }t          j        | j         d         |z   f| j         dd         z   | j                  }t	          | j         d                   D ]k}| |         t          ||          z  }t	          |dz             D ]=}|||z   xx         |t          ||          z  t          ||z   ||z             z  z  cc<   >l|S )a  
        Raise a degree of a polynomial in the Bernstein basis.

        Given the coefficients of a polynomial degree `k`, return (the
        coefficients of) the equivalent polynomial of degree `k+d`.

        Parameters
        ----------
        c : array_like
            coefficient array, 1-D
        d : integer

        Returns
        -------
        array
            coefficient array, 1-D array of length `c.shape[0] + d`

        Notes
        -----
        This uses the fact that a Bernstein polynomial `b_{a, k}` can be
        identically represented as a linear combination of polynomials of
        a higher degree `k+d`:

            .. math:: b_{a, k} = comb(k, a) \sum_{j=0}^{d} b_{a+j, k+d} \
                                 comb(d, j) / comb(k+d, a+j)
        r   r9   Nr7   )r>   r<   r`   r(   r   r   )rE   dr   rJ   r{   fjs          r   r  zBPoly._raise_degree  s    8 66HGAJNj!'!*q.*QWQRR[8HHHqwqz"" 	D 	DA!uQ{{"A1q5\\ D DAE


a%1++oa!eQU0C0CCC



D
r   c                    t          |t                    st          dt          |          z            t	          j        |j                  }|j        j        d         dz
  }d|j        j	        dz
  z  }t	          j
        |j                  }t          |dz             D ]}|j        |         t          |||z
            z  |t          d          f|z            ||z
  z  z  }t          ||z
  |dz             D ]&}	||	xx         |t          |	||z
            z  z  cc<   '||j        }|                     ||j        ||j                  S )a  
        Construct a piecewise polynomial in Bernstein basis
        from a power basis polynomial.

        Parameters
        ----------
        pp : PPoly
            A piecewise polynomial in the power basis
        extrapolate : bool or 'periodic', optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used. Default is True.
        z?.from_power_basis only accepts PPoly instances. Got %s instead.r   r9   r
   ry   N)r   r   r   r   r<   r   rF   rE   r>   r   r   r   r   r   rI   r   r   )
r   pprI   rH   r   r   rE   r{   r   r  s
             r   from_power_basiszBPoly.from_power_basis  sP    "e$$ 	: .04R9 : : : Yrt__DJqMA	!$OBD!!qs 	/ 	/AT!WuQ!}},r5;;.2E/F1/MMF1Q3!__ / /!q!A#../ .K!!!RT;@@@r   c           	         t          j        |          }t          |          t                    k    rt          d          t          j        |dd         |dd         z
  dk              rt          d          t          |          dz
  }	 t          fdt          |          D                       }n"# t          $ r}t          d          |d}~ww xY w|dg|z  }nlt          |t          t           j
        f          r|g|z  }t          |t          |                    }t	          d |D                       rt          d	          g }t          |          D ]}	|	         |	dz            }}
||	         t          |
          t          |          }}n||	         dz   }t          |d
z  t          |
                    }t          ||z
  t          |                    }t          ||z
  t          |                    }||z   |k    rHd||	         t          |
          ||	dz            t          |          ||	         fz  }t          |          |t          |
          k    r|t          |          k    st          d          t                              ||	         ||	dz            |
d|         |d|                   }t          |          |k     r+t                              ||t          |          z
            }|                    |           t          j        |          } | |                    dd          ||          S )aB
  
        Construct a piecewise polynomial in the Bernstein basis,
        compatible with the specified values and derivatives at breakpoints.

        Parameters
        ----------
        xi : array_like
            sorted 1-D array of x-coordinates
        yi : array_like or list of array_likes
            ``yi[i][j]`` is the ``j`` th derivative known at ``xi[i]``
        orders : None or int or array_like of ints. Default: None.
            Specifies the degree of local polynomials. If not None, some
            derivatives are ignored.
        extrapolate : bool or 'periodic', optional
            If bool, determines whether to extrapolate to out-of-bounds points
            based on first and last intervals, or to return NaNs.
            If 'periodic', periodic extrapolation is used. Default is True.

        Notes
        -----
        If ``k`` derivatives are specified at a breakpoint ``x``, the
        constructed polynomial is exactly ``k`` times continuously
        differentiable at ``x``, unless the ``order`` is provided explicitly.
        In the latter case, the smoothness of the polynomial at
        the breakpoint is controlled by the ``order``.

        Deduces the number of derivatives to match at each end
        from ``order`` and the number of derivatives available. If
        possible it uses the same number of derivatives from
        each end; if the number is odd it tries to take the
        extra one from y2. In any case if not enough derivatives
        are available at one end or another it draws enough to
        make up the total from the other end.

        If the order is too high and not enough derivatives are available,
        an exception is raised.

        Examples
        --------
        >>> from cupyx.scipy.interpolate import BPoly
        >>> BPoly.from_derivatives([0, 1], [[1, 2], [3, 4]])

        Creates a polynomial `f(x)` of degree 3, defined on `[0, 1]`
        such that `f(0) = 1, df/dx(0) = 2, f(1) = 3, df/dx(1) = 4`

        >>> BPoly.from_derivatives([0, 1, 2], [[0, 1], [0], [2]])

        Creates a piecewise polynomial `f(x)`, such that
        `f(0) = f(1) = 0`, `f(2) = 2`, and `df/dx(0) = 1`.
        Based on the number of derivatives provided, the order of the
        local polynomials is 2 on `[0, 1]` and 1 on `[1, 2]`.
        Notice that no restriction is imposed on the derivatives at
        ``x = 1`` and ``x = 2``.

        Indeed, the explicit form of the polynomial is::

            f(x) = | x * (1 - x),  0 <= x < 1
                   | 2 * (x - 1),  1 <= x <= 2

        So that f'(1-0) = -1 and f'(1+0) = 2
        z&xi and yi need to have the same lengthr9   Nr   z)x coordinates are not in increasing orderc              3   t   K   | ]2}t          |                   t          |d z                      z   V  3dS r9   N)rX   )r   iyis     r   	<genexpr>z)BPoly.from_derivatives.<locals>.<genexpr>  s@      @@!C1JJR!W-@@@@@@r   z0Using a 1-D array for y? Please .reshape(-1, 1).c              3   "   K   | ]
}|d k    V  dS r   r   )r   os     r   r  z)BPoly.from_derivatives.<locals>.<genexpr>%  s&      **a16******r   zOrders must be positive.ry   zPPoint %g has %d derivatives, point %g has %d derivatives, but order %d requestedz0`order` input incompatible with length y1 or y2.)r<   rA   rX   r   anyr   r   r   r   r   integerminr   _construct_from_derivativesr  r   swapaxes)r   xir  ordersrI   r   r   erE   r  y1y2n1n2r   mesgr|   s     `              r   from_derivativeszBPoly.from_derivatives  sI   ~ \"r77c"ggEFFF8BqrrFRVOq()) 	JHIII GGaK	@@@@uQxx@@@@@AA 	 	 	B 	
 >VaZFF&3"566 & AAs6{{##A**6***** = !;<<<q 	 	AUBqsGBay R#b''B1IaKAs2ww''RR))RR))b5A::J "1s2ww1Q3R&)MMMD %T***c"gg"B--$ &9 : : : 11"Q%AaC24SbS'2crc7D DA1vvzz''1s1vv:66HHQKKKKLOOs1::a##R555s   (B; ;
CCCc                    t          j        |          t          j        |          }}|j        dd         |j        dd         k    r-t          d                    |j        |j                            |j        |j        }}t          j        |t           j                  st          j        |t           j                  rt           j        }nt           j	        }t          |          t          |          }}||z   }	t          j        ||z   f|j        dd         z   |          }
t          d|          D ]r}||         t          j        |	|z
  |          z  || z
  |z  z  |
|<   t          d|          D ]2}|
|xx         d||z   z  t          ||          z  |
|         z  z  cc<   3st          d|          D ]}||         t          j        |	|z
  |          z  d|z  z  || z
  |z  z  |
| dz
  <   t          d|          D ]=}|
| dz
  xx         d|dz   z  t          ||dz             z  |
| |z            z  z  cc<   >|
S )aR  
        Compute the coefficients of a polynomial in the Bernstein basis
        given the values and derivatives at the edges.

        Return the coefficients of a polynomial in the Bernstein basis
        defined on ``[xa, xb]`` and having the values and derivatives at the
        endpoints `xa` and `xb` as specified by `ya`` and `yb`.

        The polynomial constructed is of the minimal possible degree, i.e.,
        if the lengths of `ya` and `yb` are `na` and `nb`, the degree
        of the polynomial is ``na + nb - 1``.

        Parameters
        ----------
        xa : float
            Left-hand end point of the interval
        xb : float
            Right-hand end point of the interval
        ya : array_like
            Derivatives at `xa`. `ya[0]` is the value of the function, and
            `ya[i]` for ``i > 0`` is the value of the ``i``th derivative.
        yb : array_like
            Derivatives at `xb`.

        Returns
        -------
        array
            coefficient array of a polynomial having specified derivatives

        Notes
        -----
        This uses several facts from life of Bernstein basis functions.
        First of all,

            .. math:: b'_{a, n} = n (b_{a-1, n-1} - b_{a, n-1})

        If B(x) is a linear combination of the form

            .. math:: B(x) = \sum_{a=0}^{n} c_a b_{a, n},

        then :math: B'(x) = n \sum_{a=0}^{n-1} (c_{a+1} - c_{a}) b_{a, n-1}.
        Iterating the latter one, one finds for the q-th derivative

            .. math:: B^{q}(x) = n!/(n-q)! \sum_{a=0}^{n-q} Q_a b_{a, n-q},

        with

            .. math:: Q_a = \sum_{j=0}^{q} (-)^{j+q} comb(q, j) c_{j+a}

        This way, only `a=0` contributes to :math: `B^{q}(x = xa)`, and
        `c_q` are found one by one by iterating `q = 0, ..., na`.

        At ``x = xb`` it's the same with ``a = n - q``.
        r9   Nz*Shapes of ya {} and yb {} are incompatibler7   r   r6   )r<   rA   r>   r   r   r(   r   r   r   rz   rX   r=   r   r   r   r   )xaxbyaybdtadtbdtnanbr   rE   qr  s                r   r   z!BPoly._construct_from_derivativesE  s\   p b!!4<#3#3B8ABB<28ABB<''I$fRXrx88: : : 8RXSOC!566 	T%9::	BBBR#b''BGJ2x"(122,.b999 q" 	9 	9Aa549QUA..."r'A=AaD1a[[ 9 9!qseAqkk1AaD889 q" 	A 	AAediAq111R!G;rBwlJAqbdG1a[[ A A1"Q$B!A#;q!A#6A2a4@@A r   rs   r
   NN)r   r   r   r   r   r   r   rx   r   r   staticmethodr  r   r  r*  r   r   r   r   r   r   y  s       I IV3 3 32L 2L 2L 2Lh8G 8G 8G 8Gt=! =! =! =!~- - -
  &.FN% % \%N  A  A  A [ AD t6 t6 t6 [t6l U U \U U Ur   r   c                   n    e Zd ZdZddZedd            Zd Zd ZddZ	d Z
d	 Zd
 Zd ZddZddZdS )NdPPolya  
    Piecewise tensor product polynomial

    The value at point ``xp = (x', y', z', ...)`` is evaluated by first
    computing the interval indices `i` such that::

        x[0][i[0]] <= x' < x[0][i[0]+1]
        x[1][i[1]] <= y' < x[1][i[1]+1]
        ...

    and then computing::

        S = sum(c[k0-m0-1,...,kn-mn-1,i[0],...,i[n]]
                * (xp[0] - x[0][i[0]])**m0
                * ...
                * (xp[n] - x[n][i[n]])**mn
                for m0 in range(k[0]+1)
                ...
                for mn in range(k[n]+1))

    where ``k[j]`` is the degree of the polynomial in dimension j. This
    representation is the piecewise multivariate power basis.

    Parameters
    ----------
    c : ndarray, shape (k0, ..., kn, m0, ..., mn, ...)
        Polynomial coefficients, with polynomial order `kj` and
        `mj+1` intervals for each dimension `j`.
    x : ndim-tuple of ndarrays, shapes (mj+1,)
        Polynomial breakpoints for each dimension. These must be
        sorted in increasing order.
    extrapolate : bool, optional
        Whether to extrapolate to out-of-bounds points based on first
        and last intervals, or to return NaNs. Default: True.

    Attributes
    ----------
    x : tuple of ndarrays
        Breakpoints.
    c : ndarray
        Coefficients of the polynomials.

    See also
    --------
    PPoly : piecewise polynomials in 1D

    Notes
    -----
    High-order polynomials in the power basis can be numerically
    unstable.
    Nc           	      (   t          d |D                       | _        t          j        |          | _        |d}t          |          | _        t          | j                  }t          d | j        D                       rt          d          t          d | j        D                       rt          d          |j
        d|z  k     rt          d          t          d	 | j        D                       rt          d
          t          d t          |j        |d|z           | j                  D                       rt          d          |                     | j        j                  }t          j        | j        |          | _        d S )Nc              3   V   K   | ]$}t          j        |t           j                   V  %dS )r7   N)r<   r   rz   r   vs     r   r  z#NdPPoly.__init__.<locals>.<genexpr>  sO       / /'( -T\# # # / / / / / /r   Tc              3   ,   K   | ]}|j         d k    V  dS r  )r   r<  s     r   r  z#NdPPoly.__init__.<locals>.<genexpr>  s(      ++qqv{++++++r   z"x arrays must all be 1-dimensionalc              3   ,   K   | ]}|j         d k     V  dS )ry   NrT   r<  s     r   r  z#NdPPoly.__init__.<locals>.<genexpr>  s(      **aqvz******r   z+x arrays must all contain at least 2 pointsry   z(c must have at least 2*len(x) dimensionsc              3   l   K   | ]/}t          j        |d d         |dd         z
  dk               V  0dS )r9   Nr6   r   )r<   r  r<  s     r   r  z#NdPPoly.__init__.<locals>.<genexpr>  sE      <<tx!""#2#*++<<<<<<r   z)x-coordinates are not in increasing orderc              3   8   K   | ]\  }}||j         d z
  k    V  dS r  rT   )r   r{   r|   s      r   r  z#NdPPoly.__init__.<locals>.<genexpr>  s0      MM41aqAFQJMMMMMMr   z/x and c do not agree on the number of intervalsr7   )r   rF   r<   rA   rE   r   rI   rX   r  r   r   zipr>   r   r(   r   )r   rE   rF   rI   r   r(   s         r   r   zNdPPoly.__init__  s    / /,-/ / / / /aK,,46{{++DF+++++ 	CABBB**46***** 	LJKKK6AdF??GHHH<<TV<<<<< 	JHIIIMM3qwtAdF{/CTV+L+LMMMMM 	PNOOO--'e<<<r   c                 l    t                               |           }||_        ||_        |d}||_        |S )aI  
        Construct the piecewise polynomial without making checks.

        Takes the same parameters as the constructor. Input arguments
        ``c`` and ``x`` must be arrays of the correct shape and type.  The
        ``c`` array can only be of dtypes float and complex, and ``x``
        array must have dtype float.
        NT)r   r   rE   rF   rI   )r   rE   rF   rI   r   s        r   r   zNdPPoly.construct_fast  s;     ~~c""K&r   c                     t          j        |t           j                  s)t          j        | j        j        t           j                  rt           j        S t           j        S r
   r   r   s     r   r   zNdPPoly._get_dtype  r   r   c                     | j         j        j        s| j                                         | _         t	          | j        t                    st          | j                  | _        d S d S r
   )rE   r   r   r_   r   rF   r   r   s    r   r   zNdPPoly._ensure_c_contiguous  sS    v|( 	#V[[]]DF$&%(( 	#46]]DFFF	# 	#r   c           
         || j         }nt          |          }t          | j                  }t	          |          }|j        }t          j        |                    d|j        d                   t          j	                  }|"t          j
        |ft          j                  }nKt          j        |t          j                  }|j        dk    s|j        d         |k    rt          d          t          t!          j        | j        j        d|                             }t          t!          j        | j        j        |d|z                               }t          t!          j        | j        j        d|z  d                             }t          j        | j        j        d|         t          j                  }	t          j        |j        d         |f| j        j                  }
|                                  t-          | j                            |||          | j        |	||t          |          |
           |
                    |dd         | j        j        d|z  d         z             S )a  
        Evaluate the piecewise polynomial or its derivative

        Parameters
        ----------
        x : array-like
            Points to evaluate the interpolant at.
        nu : tuple, optional
            Orders of derivatives to evaluate. Each must be non-negative.
        extrapolate : bool, optional
            Whether to extrapolate to out-of-bounds points based on first
            and last intervals, or to return NaNs.

        Returns
        -------
        y : array-like
            Interpolated values. Shape is determined by replacing
            the interpolation axis in the original array with the shape of x.

        Notes
        -----
        Derivatives are evaluated piecewise for each polynomial
        segment, even if the polynomial is not differentiable at the
        breakpoints. The polynomial intervals are considered half-open,
        ``[a, b)``, except for the last interval which is closed
        ``[a, b]``.
        Nr6   r7   r9   r   z&invalid number of derivative orders nury   )rI   r   rX   rF   r   r>   r<   r   r   rz   r`   r?   rA   r   r   r   r   r   rE   r=   r(   r   rp   )r   rF   r   rI   r   r   dim1dim2dim3rb   rJ   s              r   r   zNdPPoly.__call__	  s   8 *KK{++K46{{$Q'''"199R#=#=)-7 7 7 :TG4:666BBb
333Bw!||rx{d22 !IJJJ2746<.//002746<QtV455662746<$01122\$&,uu-TZ@@@j!'!*d+46<@@@!!###FNN4t,,dfb!Rs	$ 	$ 	$ {{73B3<$&,qvww*??@@@r   c                 p   |dk     r|                      | |          S t          | j                  }||z  }|dk    rdS t          d          g|z  }t          d| d          ||<   | j        t          |                   }|j        |         dk    r4t          |j                  }d||<   t          j	        ||j
                  }t          j        t          j        |j        |         dd          |          }dg|j        z  }t          d          ||<   ||t          |                   z  }|| _        dS )zz
        Compute 1-D derivative along a selected dimension in-place
        May result to non-contiguous c array.
        r   Nr9   r7   r6   )_antiderivative_inplacerX   rF   r   rE   r   r>   r   r<   r`   r(   r   r   r\   r   )r   r   r   r   slrn   shpr   s           r   _derivative_inplacezNdPPoly._derivative_inplaceF  s'   
 66//T:::46{{d{ 77F++t#BTB3--BtHb		"B8D>Qrx..CCICrx000B 4;rx~q"==rBBVbg;;4
fU2YYr   c                 z   |dk    r|                      | |          S t          | j                  }||z  }t          t	          |                    }||         |d         c|d<   ||<   |t          t	          || j        j                            z   }| j                            |          }t          j	        |j
        d         |z   f|j
        dd         z   |j                  }||d| <   t          j        t          j        |j
        d         dd          |          }|d| xx         |t          d          fd|j        dz
  z  z            z  cc<   t          t	          |j                            }|||z            |d         c|d<   |||z   <   |                    |          }|                                }t#          |                    |j
        d         |j
        d         d          | j        |         |dz
             |                    |          }|                    |          }|| _        dS )zu
        Compute 1-D antiderivative along a selected dimension
        May result to non-contiguous c array.
        r   r9   Nr7   r6   r
   )rN  rX   rF   r   r   rE   r   r   r<   r`   r>   r(   r   r   r\   r   r_   rv   r   )	r   r   r   r   permrE   rn   r   perm2s	            r   rK  zNdPPoly._antiderivative_inplaceh  s   
 77++RC66646{{d{E$KK  "4j$q'Qdd5tv{33444FT""Zb*QWQRR[8g' ' '4RC4 4;qwqz1b992>>
4RC4FE$KK>GQVAX,>>?? U27^^$$%*49%5uQx"a%T	"\\%  WWYYJJrx{BHQK44dfTlBF	L 	L 	L \\%  \\$ r   c                     |                      | j                                        | j        | j                  }t          |          D ]\  }}|                    ||           |                                 |S )a#  
        Construct a new piecewise polynomial representing the derivative.

        Parameters
        ----------
        nu : ndim-tuple of int
            Order of derivatives to evaluate for each dimension.
            If negative, the antiderivative is returned.

        Returns
        -------
        pp : NdPPoly
            Piecewise polynomial of orders (k[0] - nu[0], ..., k[n] - nu[n])
            representing the derivative of this polynomial.

        Notes
        -----
        Derivatives are evaluated piecewise for each polynomial
        segment, even if the polynomial is not differentiable at the
        breakpoints. The polynomial intervals in each dimension are
        considered half-open, ``[a, b)``, except for the last interval
        which is closed ``[a, b]``.
        )r   rE   r_   rF   rI   	enumeraterN  r   r   r   r   r   r   s        r   r   zNdPPoly.derivative  ss    0 tvt7GHH }} 	+ 	+GD!!!!T****	   r   c                     |                      | j                                        | j        | j                  }t          |          D ]\  }}|                    ||           |                                 |S )a  
        Construct a new piecewise polynomial representing the antiderivative.
        Antiderivative is also the indefinite integral of the function,
        and derivative is its inverse operation.

        Parameters
        ----------
        nu : ndim-tuple of int
            Order of derivatives to evaluate for each dimension.
            If negative, the derivative is returned.

        Returns
        -------
        pp : PPoly
            Piecewise polynomial of order k2 = k + n representing
            the antiderivative of this polynomial.

        Notes
        -----
        The antiderivative returned by this function is continuous and
        continuously differentiable to order n-1, up to floating point
        rounding error.
        )r   rE   r_   rF   rI   rS  rK  r   rT  s        r   r   zNdPPoly.antiderivative  ss    0 tvt7GHH }} 	/ 	/GD!%%a....	   r   c                 l   || j         }nt          |          }t          | j                  }t	          |          |z  }| j        }t          t          |j                            }|	                    d||                    ||dz   = |	                    d|||z                       |||z   dz   = |
                    |          }t                              |                    |j        d         |j        d         d          | j        |         |          }|                    |||          }	|dk    r"|	                    |j        dd                   S |	                    |j        dd                   }| j        d|         | j        |dz   d         z   }
|                     ||
|          S )a  
        Compute NdPPoly representation for one dimensional definite integral
        The result is a piecewise polynomial representing the integral:

        .. math::
           p(y, z, ...) = \int_a^b dx\, p(x, y, z, ...)

        where the dimension integrated over is specified with the
        `axis` parameter.

        Parameters
        ----------
        a, b : float
            Lower and upper bound for integration.
        axis : int
            Dimension over which to compute the 1-D integrals
        extrapolate : bool, optional
            Whether to extrapolate to out-of-bounds points based on first
            and last intervals, or to return NaNs.

        Returns
        -------
        ig : NdPPoly or array-like
            Definite integral of the piecewise polynomial over [a, b].
            If the polynomial was 1D, an array is returned,
            otherwise, an NdPPoly object.
        Nr   r9   r6   r   ry   )rI   r   rX   rF   r   rE   r   r   r   insertr   r   r   r   r>   rx   )r   r{   r|   r   rI   r   rE   swapr   rJ   rF   s              r   integrate_1dzNdPPoly.integrate_1d  s   8 *KK{++K46{{4yy4 FE!&MM""AtDz"""NAtD4K()))q!KK  171:qwqz2!F!F!%-8 ! : : kk!QKk88 199;;qwqrr{+++AGABBK((AuutAvww/A&&q!&EEEr   c                    t          | j                  }|| j        }nt          |          }t	          |d          rt          |          |k    rt          d          |                                  | j        }t          |          D ]\  }\  }}t          t          |j                            }|                    d|||z
                      |||z
  dz   = |                    |          }t                              || j        |         |          }	|	                    |||          }
|
                    |j        dd                   }|S )ap  
        Compute a definite integral over a piecewise polynomial.

        Parameters
        ----------
        ranges : ndim-tuple of 2-tuples float
            Sequence of lower and upper bounds for each dimension,
            ``[(a[0], b[0]), ..., (a[ndim-1], b[ndim-1])]``
        extrapolate : bool, optional
            Whether to extrapolate to out-of-bounds points based on first
            and last intervals, or to return NaNs.

        Returns
        -------
        ig : array_like
            Definite integral of the piecewise polynomial over
            [a[0], b[0]] x ... x [a[ndim-1], b[ndim-1]]
        N__len__z&Range not a sequence of correct lengthr9   r   ry   )rX   rF   rI   r   hasattrr   r   rE   rS  r   r   r   rW  r   r   r   rx   r   r>   )r   rangesrI   r   rE   r   r{   r|   rX  r   rJ   s              r   rx   zNdPPoly.integrate
	  sE   ( 46{{*KK{++Kvy)) 	GS[[D-@-@EFFF!!### F"6** 		) 		)IAv1af&&DKK4q>***TAX\"D!!A$$Qq	{$KKA++a+<<CAGABBK((AAr   r
   r6  )r   r   r   r   r   r   r   r   r   r   rN  rK  r   r   rY  rx   r   r   r   r9  r9    s        2 2h= = = =.    ["     # # #;A ;A ;A ;Az     D& & &P  @  @8F 8F 8F 8Ft- - - - - -r   r9  r
   )&r   r<   
cupy._corer   cupy._core._scalarr   cupyx.scipyr   r    cupyx.scipy.interpolate._bspliner   r   numpyr   r   r   ImportErrorMAX_DIMSTYPES	INT_TYPESINTERVAL_KERNEL	RawModuler@   PPOLY_KERNELrD   BPOLY_KERNELr   r4   rQ   rp   rv   r   r   r   r   r   r   r9  r   r   r   <module>rk     s*           + + + + + + ' ' ' ' ' ' @ @ @ @ @ @ @ @    PEE P P PP P P P PP
 	,-K 	]~ !$.	/%'DFG G G
HT t~	;;U;;;>>>>>	??????	@ 	;:E:::	;= = =GR t~	;;U;;;> > >  )% )% )%XF' F' F'RE E E4/! /! /!d.2 .2 .2b   ,Z Z Z Z Z Z Z ZzlA lA lA lA lAJ lA lA lA^b b b b bJ b b bJY Y Y Y Y Y Y Y Y Ys   1 <<