diff --git a/CHANGELOG.md b/CHANGELOG.md
index aae99c4..e8d93c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
 # Changelog
 
+## v0.11.0
+
+* Internal re-design `SplinePPForm` and `NdGridSplinePPForm` classes [#17](https://github.com/espdev/csaps/issues/17):
+    - Remove `shape` and `axis` properties and reshaping data in these classes
+    - `NdGridSplinePPForm` coefficients array for 1D grid now is 1-d instead of 2-d
+* Refactoring the code and decrease memory consumption
+* Add `overload` type-hints for `csaps` function signatures
+
 ## v0.10.1
 
 * Fix call of `numpy.pad` function for numpy <1.17 [#15](https://github.com/espdev/csaps/issues/15)
diff --git a/README.md b/README.md
index f716116..260bc08 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@
 **csaps** is a Python package for univariate, multivariate and n-dimensional grid data approximation using cubic smoothing splines.
 The package can be useful in practical engineering tasks for data approximation and smoothing.
 
-## Installation
+## Installing
 
 Use pip for installing:
 
@@ -89,20 +89,22 @@ plt.show()
 
 ## Documentation
 
-More examples of usage and the full documentation can be found at ReadTheDocs.
-
-https://csaps.readthedocs.io
+More examples of usage and the full documentation can be found at https://csaps.readthedocs.io.
 
 ## Testing
 
 pytest, tox and Travis CI are used for testing. Please see [tests](tests).
 
-## Algorithms and implementations
+## Algorithm and Implementation
 
-**csaps** package is a Python modified port of MATLAB [CSAPS](https://www.mathworks.com/help/curvefit/csaps.html) function that is an implementation of 
+**csaps** Python package is inspired by MATLAB [CSAPS](https://www.mathworks.com/help/curvefit/csaps.html) function that is an implementation of 
 Fortran routine SMOOTH from [PGS](http://pages.cs.wisc.edu/~deboor/pgs/) (originally written by Carl de Boor).
 
-[csaps-cpp](https://github.com/espdev/csaps-cpp) C++11 Eigen based implementation of the algorithm.
+Also the algothithm implementation in other languages:
+
+* [csaps-rs](https://github.com/espdev/csaps-rs) Rust ndarray/sprs based implementation
+* [csaps-cpp](https://github.com/espdev/csaps-cpp) C++11 Eigen based implementation (incomplete)
+
 
 ## References
 
diff --git a/csaps/__init__.py b/csaps/__init__.py
index adc8bd9..2aea816 100644
--- a/csaps/__init__.py
+++ b/csaps/__init__.py
@@ -23,7 +23,6 @@ from csaps._sspndg import (
 )
 from csaps._types import (
     UnivariateDataType,
-    UnivariateVectorizedDataType,
     MultivariateDataType,
     NdGridDataType,
 )
@@ -46,7 +45,6 @@ __all__ = [
 
     # Type-hints
     'UnivariateDataType',
-    'UnivariateVectorizedDataType',
     'MultivariateDataType',
     'NdGridDataType',
 ]
diff --git a/csaps/_shortcut.py b/csaps/_shortcut.py
index fee3b53..474f65f 100644
--- a/csaps/_shortcut.py
+++ b/csaps/_shortcut.py
@@ -6,50 +6,93 @@ The module provised `csaps` shortcut function for smoothing data
 """
 
 from collections import abc as c_abc
-from typing import Optional, Union, Sequence, NamedTuple
-
-import numpy as np
+from typing import Optional, Union, Sequence, NamedTuple, overload
 
 from ._base import ISmoothingSpline
 from ._sspumv import CubicSmoothingSpline
 from ._sspndg import ndgrid_prepare_data_sites, NdGridCubicSmoothingSpline
-from ._types import (
-    UnivariateDataType,
-    UnivariateVectorizedDataType,
-    NdGridDataType,
-)
-
-_XDataType = Union[UnivariateDataType, NdGridDataType]
-_YDataType = Union[UnivariateVectorizedDataType, np.ndarray]
-_XiDataType = Optional[Union[UnivariateDataType, NdGridDataType]]
-_WeightsDataType = Optional[Union[UnivariateDataType, NdGridDataType]]
-_SmoothDataType = Optional[Union[float, Sequence[Optional[float]]]]
+from ._types import UnivariateDataType, MultivariateDataType, NdGridDataType
 
 
 class AutoSmoothingResult(NamedTuple):
     """The result for auto smoothing for `csaps` function"""
 
-    values: _YDataType
+    values: MultivariateDataType
     """Smoothed data values"""
 
-    smooth: _SmoothDataType
+    smooth: Union[float, Sequence[Optional[float]]]
     """The calculated smoothing parameter"""
 
 
-_ReturnType = Union[
-    _YDataType,
-    AutoSmoothingResult,
-    ISmoothingSpline,
-]
+# **************************************
+# csaps signatures
+#
+@overload
+def csaps(xdata: UnivariateDataType,
+          ydata: MultivariateDataType,
+          *,
+          weights: Optional[UnivariateDataType] = None,
+          smooth: Optional[float] = None,
+          axis: Optional[int] = None) -> ISmoothingSpline: ...
+
+
+@overload
+def csaps(xdata: UnivariateDataType,
+          ydata: MultivariateDataType,
+          xidata: UnivariateDataType,
+          *,
+          weights: Optional[UnivariateDataType] = None,
+          axis: Optional[int] = None) -> AutoSmoothingResult: ...
+
+
+@overload
+def csaps(xdata: UnivariateDataType,
+          ydata: MultivariateDataType,
+          xidata: UnivariateDataType,
+          *,
+          smooth: float,
+          weights: Optional[UnivariateDataType] = None,
+          axis: Optional[int] = None) -> MultivariateDataType: ...
+
+
+@overload
+def csaps(xdata: NdGridDataType,
+          ydata: MultivariateDataType,
+          *,
+          weights: Optional[NdGridDataType] = None,
+          smooth: Optional[Sequence[float]] = None,
+          axis: Optional[int] = None) -> ISmoothingSpline: ...
+
+
+@overload
+def csaps(xdata: NdGridDataType,
+          ydata: MultivariateDataType,
+          xidata: NdGridDataType,
+          *,
+          weights: Optional[NdGridDataType] = None,
+          axis: Optional[int] = None) -> AutoSmoothingResult: ...
+
+
+@overload
+def csaps(xdata: NdGridDataType,
+          ydata: MultivariateDataType,
+          xidata: NdGridDataType,
+          *,
+          smooth: Sequence[float],
+          weights: Optional[NdGridDataType] = None,
+          axis: Optional[int] = None) -> MultivariateDataType: ...
+#
+# csaps signatures
+# **************************************
 
 
-def csaps(xdata: _XDataType,
-          ydata: _YDataType,
-          xidata: _XiDataType = None,
+def csaps(xdata: Union[UnivariateDataType, NdGridDataType],
+          ydata: MultivariateDataType,
+          xidata: Optional[Union[UnivariateDataType, NdGridDataType]] = None,
           *,
-          weights: _WeightsDataType = None,
-          smooth: _SmoothDataType = None,
-          axis: Optional[int] = None) -> _ReturnType:
+          weights: Optional[Union[UnivariateDataType, NdGridDataType]] = None,
+          smooth: Optional[Union[float, Sequence[float]]] = None,
+          axis: Optional[int] = None) -> Union[MultivariateDataType, ISmoothingSpline, AutoSmoothingResult]:
     """Smooths the univariate/multivariate/gridded data or computes the corresponding splines
 
     This function might be used as the main API for smoothing any data.
diff --git a/csaps/_sspndg.py b/csaps/_sspndg.py
index c275d37..030b9a1 100644
--- a/csaps/_sspndg.py
+++ b/csaps/_sspndg.py
@@ -37,82 +37,64 @@ class NdGridSplinePPForm(SplinePPFormBase[ty.Sequence[np.ndarray], ty.Tuple[int,
 
     Parameters
     ----------
-    breaks : np.ndarray
-        Breaks values 1-D array
+    breaks : Sequence[np.ndarray]
+        The sequence of the breaks 1-D arrays for each dimension
+
     coeffs : np.ndarray
-        Spline coefficients N-D array
+        Tensor-product spline coefficients N-D array
+
     """
 
     def __init__(self, breaks: ty.Sequence[np.ndarray], coeffs: np.ndarray) -> None:
         self._breaks = breaks
         self._coeffs = coeffs
         self._pieces = tuple(x.size - 1 for x in breaks)
+        self._order = tuple(s // p for s, p in zip(coeffs.shape, self._pieces))
         self._ndim = len(breaks)
 
-        if self._ndim > 1:
-            self._order = tuple(s // p for s, p in zip(coeffs.shape, self._pieces))
-        else:
-            # the corner case for univariate spline that is represented as 1d-grid
-            self._order = (coeffs.shape[1] // self._pieces[0], )
-
     @property
     def breaks(self) -> ty.Sequence[np.ndarray]:
+        """Returns the sequence of the data breaks for each dimension"""
         return self._breaks
 
     @property
     def coeffs(self) -> np.ndarray:
+        """Returns n-d array of tensor-product n-d grid spline coefficients"""
         return self._coeffs
 
     @property
     def order(self) -> ty.Tuple[int, ...]:
+        """Returns the tuple of the spline orders for each dimension"""
         return self._order
 
     @property
     def pieces(self) -> ty.Tuple[int, ...]:
+        """Returns the tuple of the spline pieces for each dimension"""
         return self._pieces
 
     @property
     def ndim(self) -> int:
+        """Returns the dimensionality of n-d grid data"""
         return self._ndim
 
-    @property
-    def shape(self) -> ty.Tuple[int, ...]:
-        """Returns the original data shape
-        """
-        return tuple(x.size for x in self.breaks)
-
     def evaluate(self, xi: ty.Sequence[np.ndarray]) -> np.ndarray:
+        """Evaluates the spline for given data point(s) on the n-d grid"""
         shape = tuple(x.size for x in xi)
 
         coeffs = self.coeffs
-        coeffs_shape = list(coeffs.shape)
+        coeffs_shape = coeffs.shape
 
-        d = self.ndim - 1
-        permuted_axes = (d, *range(d))
+        ndim_m1 = self.ndim - 1
+        permuted_axes = (ndim_m1, *range(ndim_m1))
 
         for i in reversed(range(self.ndim)):
-            xii = xi[i]
-            ndim = int(np.prod(coeffs_shape[:d]))
-
-            if self.ndim > 2:
-                coeffs = coeffs.reshape((ndim, self.pieces[i] * self.order[i]))
-
-            spp = SplinePPForm(
-                breaks=self.breaks[i],
-                coeffs=coeffs,
-                pieces=self.pieces[i],
-                order=self.order[i],
-                shape=(ndim, xii.size)
-            )
+            umv_ndim = int(np.prod(coeffs_shape[:ndim_m1]))
+            coeffs = coeffs.reshape((umv_ndim, self.pieces[i] * self.order[i]))
 
-            coeffs = spp.evaluate(xii)
+            coeffs = SplinePPForm(breaks=self.breaks[i], coeffs=coeffs).evaluate(xi[i])
 
-            if self.ndim > 2:
-                coeffs = coeffs.reshape((*coeffs_shape[:d], shape[i]))
-
-            if self.ndim > 1:
-                coeffs = coeffs.transpose(permuted_axes)
-                coeffs_shape = list(coeffs.shape)
+            coeffs = coeffs.reshape((*coeffs_shape[:ndim_m1], shape[i])).transpose(permuted_axes)
+            coeffs_shape = coeffs.shape
 
         return coeffs.reshape(shape)
 
@@ -261,4 +243,6 @@ class NdGridCubicSmoothingSpline(ISmoothingSpline[NdGridSplinePPForm, ty.Tuple[f
                 coeffs = coeffs.transpose(permute_axes)
                 coeffs_shape = list(coeffs.shape)
 
+        coeffs = coeffs.squeeze()
+
         return NdGridSplinePPForm(breaks=self._xdata, coeffs=coeffs), tuple(reversed(smooths))
diff --git a/csaps/_sspumv.py b/csaps/_sspumv.py
index 38cc955..56e0885 100644
--- a/csaps/_sspumv.py
+++ b/csaps/_sspumv.py
@@ -14,7 +14,7 @@ import scipy.sparse as sp
 import scipy.sparse.linalg as la
 
 from ._base import SplinePPFormBase, ISmoothingSpline
-from ._types import UnivariateDataType, UnivariateVectorizedDataType, MultivariateDataType
+from ._types import UnivariateDataType, MultivariateDataType
 from ._reshape import from_2d, to_2d
 
 
@@ -29,62 +29,42 @@ class SplinePPForm(SplinePPFormBase[np.ndarray, int]):
     coeffs : np.ndarray
         Spline coefficients 2-D array
 
-    ndim : int
-        Spline dimension
-
-    shape : Sequence[int]
-        It determines Y data shape
-
-    axis : int
-        Axis along which values are assumed to be varying
     """
 
-    def __init__(self, breaks: np.ndarray, coeffs: np.ndarray, order: int, pieces: int,
-                 shape: ty.Sequence[int], axis: int = -1) -> None:
+    def __init__(self, breaks: np.ndarray, coeffs: np.ndarray) -> None:
         self._breaks = breaks
         self._coeffs = coeffs
-        self._order = order
-        self._pieces = pieces
+        self._pieces = breaks.size - 1
+        self._order = coeffs.shape[1] // self._pieces
         self._ndim = coeffs.shape[0]
 
-        self._shape = tuple(shape)
-        self._axis = axis
-
     @property
     def breaks(self) -> np.ndarray:
+        """Returns the breaks array"""
         return self._breaks
 
     @property
     def coeffs(self) -> np.ndarray:
+        """Returns the spline coefficients 2-D array"""
         return self._coeffs
 
     @property
     def order(self) -> int:
+        """Returns the spline order"""
         return self._order
 
     @property
     def pieces(self) -> int:
+        """Returns the number of the spline pieces"""
         return self._pieces
 
     @property
     def ndim(self) -> int:
+        """Returns dimensionality (>1 for multivariate data)"""
         return self._ndim
 
-    @property
-    def shape(self) -> ty.Tuple[int, ...]:
-        """Returns the original data shape
-        """
-        return self._shape
-
-    @property
-    def axis(self) -> int:
-        """Returns the data axis along the spline will be evaluated
-        """
-        return self._axis
-
     def evaluate(self, xi: np.ndarray) -> np.ndarray:
-        shape = list(self.shape)
-        shape[self.axis] = xi.size
+        """Evaluates the spline for the given data point(s)"""
 
         # For each data site, compute its break interval
         mesh = self.breaks[1:-1]
@@ -107,10 +87,6 @@ class SplinePPForm(SplinePPFormBase[np.ndarray, int]):
             index += self.pieces
             values = xi * values + self.coeffs[:, index]
 
-        if values.shape != shape:
-            # Reshape values 2-D NxM array to N-D array with original shape
-            values = from_2d(values, shape, self.axis)
-
         return values
 
 
@@ -144,7 +120,7 @@ class CubicSmoothingSpline(ISmoothingSpline[SplinePPForm, float, UnivariateDataT
 
     def __init__(self,
                  xdata: UnivariateDataType,
-                 ydata: UnivariateVectorizedDataType,
+                 ydata: MultivariateDataType,
                  weights: ty.Optional[UnivariateDataType] = None,
                  smooth: ty.Optional[float] = None,
                  axis: int = -1):
@@ -167,7 +143,17 @@ class CubicSmoothingSpline(ISmoothingSpline[SplinePPForm, float, UnivariateDataT
         if xi.ndim > 1:  # pragma: no cover
             raise ValueError("'xi' data must be a 1-d array.")
 
-        return self._spline.evaluate(xi)
+        yi = self._spline.evaluate(xi)
+
+        shape = list(self._shape)
+        shape[self._axis] = xi.size
+        shape = tuple(shape)
+
+        if yi.shape != shape:
+            # Reshape values 2-D NxM array to N-D array with original shape
+            yi = from_2d(yi, shape, self._axis)
+
+        return yi
 
     @property
     def smooth(self) -> float:
@@ -246,75 +232,66 @@ class CubicSmoothingSpline(ISmoothingSpline[SplinePPForm, float, UnivariateDataT
         dy = np.diff(self._ydata, axis=1)
         dy_dx = dy / dx
 
-        if pcount > 2:
-            # Create diagonal sparse matrices
-            diags_r = np.vstack((dx[1:], 2 * (dx[1:] + dx[:-1]), dx[:-1]))
-            r = sp.spdiags(diags_r, [-1, 0, 1], pcount - 2, pcount - 2)
+        if pcount == 2:
+            # The corner case for the data with 2 points (1 breaks interval)
+            # In this case we have 2-ordered spline and linear interpolation in fact
+            yi = self._ydata[:, 0][:, np.newaxis]
+            coeffs = np.hstack((dy_dx, yi))
+
+            spline = SplinePPForm(breaks=self._xdata, coeffs=coeffs)
+            p = 1.
 
-            odx = 1. / dx
-            diags_qt = np.vstack((odx[:-1], -(odx[1:] + odx[:-1]), odx[1:]))
-            qt = sp.diags(diags_qt, [0, 1, 2], (pcount - 2, pcount))
+            return spline, p
 
-            ow = 1. / self._weights
-            osqw = 1. / np.sqrt(self._weights)  # type: np.ndarray
-            w = sp.diags(ow, 0, (pcount, pcount))
-            qtw = qt @ sp.diags(osqw, 0, (pcount, pcount))
+        # Create diagonal sparse matrices
+        diags_r = np.vstack((dx[1:], 2 * (dx[1:] + dx[:-1]), dx[:-1]))
+        r = sp.spdiags(diags_r, [-1, 0, 1], pcount - 2, pcount - 2)
 
-            # Solve linear system for the 2nd derivatives
-            qtwq = qtw @ qtw.T
+        dx_recip = 1. / dx
+        diags_qtw = np.vstack((dx_recip[:-1], -(dx_recip[1:] + dx_recip[:-1]), dx_recip[1:]))
+        diags_sqrw_recip = 1. / np.sqrt(self._weights)
 
-            if smooth is None:
-                p = self._compute_smooth(r, qtwq)
-            else:
-                p = smooth
+        qtw = (sp.diags(diags_qtw, [0, 1, 2], (pcount - 2, pcount)) @
+               sp.diags(diags_sqrw_recip, 0, (pcount, pcount)))
+        qtw = qtw @ qtw.T
 
-            a = (6. * (1. - p)) * qtwq + p * r
-            b = np.diff(dy_dx, axis=1).T
+        if smooth is None:
+            p = self._compute_smooth(r, qtw)
+        else:
+            p = smooth
 
-            u = la.spsolve(a, b)
-            if u.ndim < 2:
-                u = u[np.newaxis]
-            if self._ydim == 1:
-                u = u.T
+        pp = (6. * (1. - p))
 
-            dx = dx[:, np.newaxis]
+        # Solve linear system for the 2nd derivatives
+        a = pp * qtw + p * r
+        b = np.diff(dy_dx, axis=1).T
 
-            pad = functools.partial(np.pad, pad_width=[(1, 1), (0, 0)], mode='constant')
+        u = la.spsolve(a, b)
+        if u.ndim < 2:
+            u = u[np.newaxis]
+        if self._ydim == 1:
+            u = u.T
 
-            d1 = np.diff(pad(u), axis=0) / dx
-            d2 = np.diff(pad(d1), axis=0)
+        dx = dx[:, np.newaxis]
 
-            yi = self._ydata.T - ((6. * (1. - p)) * w) @ d2
-            c3 = pad(p * u)
-            c2 = np.diff(yi, axis=0) / dx - dx * (2. * c3[:-1, :] + c3[1:, :])
+        vpad = functools.partial(np.pad, pad_width=[(1, 1), (0, 0)], mode='constant')
 
-            coeffs = np.vstack((
-                np.diff(c3, axis=0) / dx,
-                3. * c3[:-1, :],
-                c2,
-                yi[:-1, :],
-            )).T
+        d1 = np.diff(vpad(u), axis=0) / dx
+        d2 = np.diff(vpad(d1), axis=0)
 
-            order = 4
-            pieces = coeffs.shape[1] // order
-        else:
-            # The corner case for the data with 2 points.
-            yi = self._ydata[:, 0][:, np.newaxis]
-            coeffs = np.hstack((dy_dx, yi))
+        diags_w_recip = 1. / self._weights
+        w = sp.diags(diags_w_recip, 0, (pcount, pcount))
 
-            order = 2
-            pieces = 1
+        yi = self._ydata.T - (pp * w) @ d2
+        pu = vpad(p * u)
 
-            p = 1.
+        p1 = np.diff(pu, axis=0) / dx
+        p2 = 3. * pu[:-1, :]
+        p3 = np.diff(yi, axis=0) / dx - dx * (2. * pu[:-1, :] + pu[1:, :])
+        p4 = yi[:-1, :]
 
-        spline = SplinePPForm(
-            breaks=self._xdata,
-            coeffs=coeffs,
-            order=order,
-            pieces=pieces,
-            shape=self._shape,
-            axis=self._axis
-        )
+        coeffs = np.vstack((p1, p2, p3, p4)).T
+        spline = SplinePPForm(breaks=self._xdata, coeffs=coeffs)
 
         return spline, p
 
@@ -324,7 +301,7 @@ class UnivariateCubicSmoothingSpline(ISmoothingSpline[SplinePPForm, float, Univa
 
     def __init__(self,
                  xdata: UnivariateDataType,
-                 ydata: UnivariateVectorizedDataType,
+                 ydata: MultivariateDataType,
                  weights: ty.Optional[UnivariateDataType] = None,
                  smooth: ty.Optional[float] = None,
                  axis: int = -1) -> None:
diff --git a/csaps/_types.py b/csaps/_types.py
index beefd9f..b960a32 100644
--- a/csaps/_types.py
+++ b/csaps/_types.py
@@ -5,32 +5,18 @@ Type-hints and type vars
 
 """
 
-import typing as ty
-import numbers
+from collections import abc
+from typing import Union, Sequence, Tuple, TypeVar
+from numbers import Number
 import numpy as np
 
 
-UnivariateDataType = ty.Union[
-    np.ndarray,
-    ty.Sequence[numbers.Number]
-]
+UnivariateDataType = Union[np.ndarray, Sequence[Number]]
+MultivariateDataType = Union[np.ndarray, abc.Sequence]
+NdGridDataType = Sequence[UnivariateDataType]
 
-UnivariateVectorizedDataType = ty.Union[
-    UnivariateDataType,
-    # FIXME: mypy does not support recursive types
-    # https://github.com/python/mypy/issues/731
-    # ty.Sequence['UnivariateVectorizedDataType']
-]
-
-MultivariateDataType = ty.Union[
-    np.ndarray,
-    ty.Sequence[UnivariateDataType]
-]
-
-NdGridDataType = ty.Sequence[UnivariateDataType]
-
-TData = ty.TypeVar('TData', np.ndarray, ty.Sequence[np.ndarray])
-TProps = ty.TypeVar('TProps', int, ty.Tuple[int, ...])
-TSmooth = ty.TypeVar('TSmooth', float, ty.Tuple[float, ...])
-TXi = ty.TypeVar('TXi', UnivariateDataType, NdGridDataType)
-TSpline = ty.TypeVar('TSpline')
+TData = TypeVar('TData', np.ndarray, Sequence[np.ndarray])
+TProps = TypeVar('TProps', int, Tuple[int, ...])
+TSmooth = TypeVar('TSmooth', float, Tuple[float, ...])
+TXi = TypeVar('TXi', UnivariateDataType, NdGridDataType)
+TSpline = TypeVar('TSpline')
diff --git a/csaps/_version.py b/csaps/_version.py
index c6e8e14..4cad2e2 100644
--- a/csaps/_version.py
+++ b/csaps/_version.py
@@ -1,3 +1,3 @@
 # -*- coding: utf-8 -*-
 
-__version__ = '0.10.1'
+__version__ = '0.11.0'

checking shapes equality is always false in evaluate method
The following condition is always false because we compare list and tuple:

https://github.com/espdev/csaps/blob/6a301dccaab25b9f345100befb486f6c2647154d/csaps/_sspumv.py#L110

We need to refactor the code to avoid performing this code in `SplinePPForm` class. It violates the single responsibility principle and also the encapsulation.

`SplinePPForm` class should know nothing about:
* shape
* axis
* other things which are not related to evaluating data

The reshaping result array should be performed in the `__call__` method of the caller class (`CubicSmoothingSpline`), but not in `SplinePPForm` class.

diff --git a/tests/test_ndgrid.py b/tests/test_ndgrid.py
index 36aa88f..28a026c 100644
--- a/tests/test_ndgrid.py
+++ b/tests/test_ndgrid.py
@@ -143,5 +143,5 @@ def test_nd_array(shape: tuple):
     sp = csaps.NdGridCubicSmoothingSpline(xdata, ydata, smooth=1.0)
     ydata_s = sp(xdata)
 
-    assert sp.spline.shape == ydata.shape
+    assert len(sp.spline.coeffs.shape) == len(ydata.shape)
     assert ydata_s == pytest.approx(ydata)
diff --git a/tests/test_univariate.py b/tests/test_univariate.py
index 45ff972..f690e51 100644
--- a/tests/test_univariate.py
+++ b/tests/test_univariate.py
@@ -132,7 +132,6 @@ def test_splineppform(y, order, pieces, ndim):
     assert s.order == order
     assert s.pieces == pieces
     assert s.ndim == ndim
-    assert s.shape == y.shape
 
 
 @pytest.mark.parametrize('shape, axis', chain(
@@ -154,11 +153,7 @@ def test_axis(shape, axis):
     y = np.arange(int(np.prod(shape))).reshape(shape)
     x = np.arange(np.array(y).shape[axis])
 
-    s = csaps.UnivariateCubicSmoothingSpline(x, y, axis=axis)
-    ys = s(x)
-
-    assert s.spline.shape == y.shape
-    assert s.spline.axis == axis
+    ys = csaps.UnivariateCubicSmoothingSpline(x, y, axis=axis)(x)
 
     np.testing.assert_allclose(ys, y)
 

pip install -e .[tests]
parse_log_pytest
pytest
pytest coverage pytest-cov coveralls flake8 flake8-colors
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///croot/attrs_1668696182826/work
certifi @ file:///croot/certifi_1671487769961/work/certifi
charset-normalizer==3.4.1
coverage==6.5.0
coveralls==3.3.1
-e git+https://github.com/espdev/csaps.git@6a301dccaab25b9f345100befb486f6c2647154d#egg=csaps
docopt==0.6.2
flake8==5.0.4
flake8-colors==0.1.9
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
idna==3.10
importlib-metadata==4.2.0
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
mccabe==0.7.0
numpy==1.19.5
packaging @ file:///croot/packaging_1671697413597/work
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pycodestyle==2.9.1
pyflakes==2.5.0
pytest==7.1.2
pytest-cov==4.1.0
requests==2.31.0
scipy==1.5.4
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typing_extensions @ file:///croot/typing_extensions_1669924550328/work
urllib3==2.0.7
zipp @ file:///croot/zipp_1672387121353/work

name: csaps
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib_metadata=4.11.3=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py37h06a4308_0
  - typing_extensions=4.4.0=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - charset-normalizer==3.4.1
      - coverage==6.5.0
      - coveralls==3.3.1
      - docopt==0.6.2
      - flake8==5.0.4
      - flake8-colors==0.1.9
      - idna==3.10
      - importlib-metadata==4.2.0
      - mccabe==0.7.0
      - numpy==1.19.5
      - pycodestyle==2.9.1
      - pyflakes==2.5.0
      - pytest-cov==4.1.0
      - requests==2.31.0
      - scipy==1.5.4
      - urllib3==2.0.7
prefix: /opt/conda/envs/csaps

tests/test_ndgrid.py::test_nd_array[1d]
tests/test_ndgrid.py::test_invalid_data[x0-y0-None-None] tests/test_ndgrid.py::test_invalid_data[x1-y1-None-None] tests/test_ndgrid.py::test_invalid_data[x2-y2-None-None] tests/test_ndgrid.py::test_invalid_data[x3-y3-None-None] tests/test_ndgrid.py::test_invalid_data[x4-y4-w4-None] tests/test_ndgrid.py::test_invalid_data[x5-y5-w5-None] tests/test_ndgrid.py::test_invalid_data[x6-y6-w6-None] tests/test_ndgrid.py::test_invalid_data[x7-y7-None-p7] tests/test_ndgrid.py::test_invalid_data[x8-y8-None-None] tests/test_ndgrid.py::test_invalid_data[x9-y9-None-None] tests/test_ndgrid.py::test_surface tests/test_ndgrid.py::test_smooth_factor[shape0-0.0] tests/test_ndgrid.py::test_smooth_factor[shape1-0.5] tests/test_ndgrid.py::test_smooth_factor[shape2-1.0] tests/test_ndgrid.py::test_smooth_factor[shape3-smooth3] tests/test_ndgrid.py::test_smooth_factor[shape4-smooth4] tests/test_ndgrid.py::test_smooth_factor[shape5-smooth5] tests/test_ndgrid.py::test_smooth_factor[shape6-0.0] tests/test_ndgrid.py::test_smooth_factor[shape7-0.5] tests/test_ndgrid.py::test_smooth_factor[shape8-1.0] tests/test_ndgrid.py::test_smooth_factor[shape9-smooth9] tests/test_ndgrid.py::test_smooth_factor[shape10-smooth10] tests/test_ndgrid.py::test_smooth_factor[shape11-smooth11] tests/test_ndgrid.py::test_smooth_factor[shape12-smooth12] tests/test_ndgrid.py::test_smooth_factor[shape13-smooth13] tests/test_ndgrid.py::test_smooth_factor[shape14-smooth14] tests/test_ndgrid.py::test_smooth_factor[shape15-smooth15] tests/test_ndgrid.py::test_smooth_factor[shape16-0.0] tests/test_ndgrid.py::test_smooth_factor[shape17-0.5] tests/test_ndgrid.py::test_smooth_factor[shape18-1.0] tests/test_ndgrid.py::test_smooth_factor[shape19-smooth19] tests/test_ndgrid.py::test_smooth_factor[shape20-smooth20] tests/test_ndgrid.py::test_smooth_factor[shape21-smooth21] tests/test_ndgrid.py::test_smooth_factor[shape22-smooth22] tests/test_ndgrid.py::test_smooth_factor[shape23-smooth23] tests/test_ndgrid.py::test_smooth_factor[shape24-0.0] tests/test_ndgrid.py::test_smooth_factor[shape25-0.5] tests/test_ndgrid.py::test_smooth_factor[shape26-1.0] tests/test_ndgrid.py::test_smooth_factor[shape27-smooth27] tests/test_ndgrid.py::test_smooth_factor[shape28-smooth28] tests/test_ndgrid.py::test_smooth_factor[shape29-smooth29] tests/test_ndgrid.py::test_smooth_factor[shape30-smooth30] tests/test_ndgrid.py::test_smooth_factor[shape31-smooth31] tests/test_ndgrid.py::test_smooth_factor[shape32-smooth32] tests/test_ndgrid.py::test_smooth_factor[shape33-smooth33] tests/test_ndgrid.py::test_nd_2pt_array[shape0] tests/test_ndgrid.py::test_nd_2pt_array[shape1] tests/test_ndgrid.py::test_nd_2pt_array[shape2] tests/test_ndgrid.py::test_nd_2pt_array[shape3] tests/test_ndgrid.py::test_nd_2pt_array[shape4] tests/test_ndgrid.py::test_nd_2pt_array[shape5] tests/test_ndgrid.py::test_nd_2pt_array[shape6] tests/test_ndgrid.py::test_nd_2pt_array[shape7] tests/test_ndgrid.py::test_nd_2pt_array[shape8] tests/test_ndgrid.py::test_nd_2pt_array[shape9] tests/test_ndgrid.py::test_nd_2pt_array[shape10] tests/test_ndgrid.py::test_nd_2pt_array[shape11] tests/test_ndgrid.py::test_nd_2pt_array[shape12] tests/test_ndgrid.py::test_nd_2pt_array[shape13] tests/test_ndgrid.py::test_nd_2pt_array[shape14] tests/test_ndgrid.py::test_nd_array[2d] tests/test_ndgrid.py::test_nd_array[3d] tests/test_ndgrid.py::test_nd_array[4d] tests/test_ndgrid.py::test_nd_array[5d] tests/test_univariate.py::test_invalid_data[x0-y0-None] tests/test_univariate.py::test_invalid_data[x1-y1-None] tests/test_univariate.py::test_invalid_data[x2-y2-None] tests/test_univariate.py::test_invalid_data[x3-y3-w3] tests/test_univariate.py::test_invalid_data[x4-y4-w4] tests/test_univariate.py::test_invalid_data[x5-y5-w5] tests/test_univariate.py::test_invalid_data[x6-y6-None] tests/test_univariate.py::test_invalid_data[x7-y7-None] tests/test_univariate.py::test_invalid_data[x8-y8-w8] tests/test_univariate.py::test_invalid_data[x9-y9-w9] tests/test_univariate.py::test_invalid_data[x10-y10-w10] tests/test_univariate.py::test_vectorize[y0] tests/test_univariate.py::test_vectorize[y1] tests/test_univariate.py::test_vectorize[y2] tests/test_univariate.py::test_vectorize[y3] tests/test_univariate.py::test_vectorize[y4] tests/test_univariate.py::test_vectorize[y5] tests/test_univariate.py::test_vectorize[y6] tests/test_univariate.py::test_vectorize[y7] tests/test_univariate.py::test_vectorize[y8] tests/test_univariate.py::test_vectorize[y9] tests/test_univariate.py::test_vectorize[y10] tests/test_univariate.py::test_vectorize[y11] tests/test_univariate.py::test_vectorize[y12] tests/test_univariate.py::test_vectorize[y13] tests/test_univariate.py::test_vectorize[y14] tests/test_univariate.py::test_vectorize[y15] tests/test_univariate.py::test_vectorize[y16] tests/test_univariate.py::test_vectorize[y17] tests/test_univariate.py::test_vectorize[y18] tests/test_univariate.py::test_splineppform[y0-2-1-1] tests/test_univariate.py::test_splineppform[y1-2-1-2] tests/test_univariate.py::test_splineppform[y2-4-2-1] tests/test_univariate.py::test_splineppform[y3-4-2-2] tests/test_univariate.py::test_splineppform[y4-4-6-1] tests/test_univariate.py::test_splineppform[y5-4-6-2] tests/test_univariate.py::test_axis[shape0--1] tests/test_univariate.py::test_axis[shape1-0] tests/test_univariate.py::test_axis[shape2--1] tests/test_univariate.py::test_axis[shape3-0] tests/test_univariate.py::test_axis[shape4--2] tests/test_univariate.py::test_axis[shape5--1] tests/test_univariate.py::test_axis[shape6-0] tests/test_univariate.py::test_axis[shape7-1] tests/test_univariate.py::test_axis[shape8--2] tests/test_univariate.py::test_axis[shape9--1] tests/test_univariate.py::test_axis[shape10-0] tests/test_univariate.py::test_axis[shape11-1] tests/test_univariate.py::test_axis[shape12--3] tests/test_univariate.py::test_axis[shape13--2] tests/test_univariate.py::test_axis[shape14--1] tests/test_univariate.py::test_axis[shape15-0] tests/test_univariate.py::test_axis[shape16-1] tests/test_univariate.py::test_axis[shape17-2] tests/test_univariate.py::test_axis[shape18--3] tests/test_univariate.py::test_axis[shape19--2] tests/test_univariate.py::test_axis[shape20--1] tests/test_univariate.py::test_axis[shape21-0] tests/test_univariate.py::test_axis[shape22-1] tests/test_univariate.py::test_axis[shape23-2] tests/test_univariate.py::test_axis[shape24--3] tests/test_univariate.py::test_axis[shape25--2] tests/test_univariate.py::test_axis[shape26--1] tests/test_univariate.py::test_axis[shape27-0] tests/test_univariate.py::test_axis[shape28-1] tests/test_univariate.py::test_axis[shape29-2] tests/test_univariate.py::test_axis[shape30--3] tests/test_univariate.py::test_axis[shape31--2] tests/test_univariate.py::test_axis[shape32--1] tests/test_univariate.py::test_axis[shape33-0] tests/test_univariate.py::test_axis[shape34-1] tests/test_univariate.py::test_axis[shape35-2] tests/test_univariate.py::test_axis[shape36--3] tests/test_univariate.py::test_axis[shape37--2] tests/test_univariate.py::test_axis[shape38--1] tests/test_univariate.py::test_axis[shape39-0] tests/test_univariate.py::test_axis[shape40-1] tests/test_univariate.py::test_axis[shape41-2] tests/test_univariate.py::test_axis[shape42--3] tests/test_univariate.py::test_axis[shape43--2] tests/test_univariate.py::test_axis[shape44--1] tests/test_univariate.py::test_axis[shape45-0] tests/test_univariate.py::test_axis[shape46-1] tests/test_univariate.py::test_axis[shape47-2] tests/test_univariate.py::test_axis[shape48--4] tests/test_univariate.py::test_axis[shape49--3] tests/test_univariate.py::test_axis[shape50--2] tests/test_univariate.py::test_axis[shape51--1] tests/test_univariate.py::test_axis[shape52-0] tests/test_univariate.py::test_axis[shape53-1] tests/test_univariate.py::test_axis[shape54-2] tests/test_univariate.py::test_axis[shape55-3] tests/test_univariate.py::test_axis[shape56--4] tests/test_univariate.py::test_axis[shape57--3] tests/test_univariate.py::test_axis[shape58--2] tests/test_univariate.py::test_axis[shape59--1] tests/test_univariate.py::test_axis[shape60-0] tests/test_univariate.py::test_axis[shape61-1] tests/test_univariate.py::test_axis[shape62-2] tests/test_univariate.py::test_axis[shape63-3] tests/test_univariate.py::test_axis[shape64--4] tests/test_univariate.py::test_axis[shape65--3] tests/test_univariate.py::test_axis[shape66--2] tests/test_univariate.py::test_axis[shape67--1] tests/test_univariate.py::test_axis[shape68-0] tests/test_univariate.py::test_axis[shape69-1] tests/test_univariate.py::test_axis[shape70-2] tests/test_univariate.py::test_axis[shape71-3] tests/test_univariate.py::test_axis[shape72--4] tests/test_univariate.py::test_axis[shape73--3] tests/test_univariate.py::test_axis[shape74--2] tests/test_univariate.py::test_axis[shape75--1] tests/test_univariate.py::test_axis[shape76-0] tests/test_univariate.py::test_axis[shape77-1] tests/test_univariate.py::test_axis[shape78-2] tests/test_univariate.py::test_axis[shape79-3] tests/test_univariate.py::test_axis[shape80--4] tests/test_univariate.py::test_axis[shape81--3] tests/test_univariate.py::test_axis[shape82--2] tests/test_univariate.py::test_axis[shape83--1] tests/test_univariate.py::test_axis[shape84-0] tests/test_univariate.py::test_axis[shape85-1] tests/test_univariate.py::test_axis[shape86-2] tests/test_univariate.py::test_axis[shape87-3] tests/test_univariate.py::test_axis[shape88--4] tests/test_univariate.py::test_axis[shape89--3] tests/test_univariate.py::test_axis[shape90--2] tests/test_univariate.py::test_axis[shape91--1] tests/test_univariate.py::test_axis[shape92-0] tests/test_univariate.py::test_axis[shape93-1] tests/test_univariate.py::test_axis[shape94-2] tests/test_univariate.py::test_axis[shape95-3] tests/test_univariate.py::test_axis[shape96--4] tests/test_univariate.py::test_axis[shape97--3] tests/test_univariate.py::test_axis[shape98--2] tests/test_univariate.py::test_axis[shape99--1] tests/test_univariate.py::test_axis[shape100-0] tests/test_univariate.py::test_axis[shape101-1] tests/test_univariate.py::test_axis[shape102-2] tests/test_univariate.py::test_axis[shape103-3] tests/test_univariate.py::test_axis[shape104--4] tests/test_univariate.py::test_axis[shape105--3] tests/test_univariate.py::test_axis[shape106--2] tests/test_univariate.py::test_axis[shape107--1] tests/test_univariate.py::test_axis[shape108-0] tests/test_univariate.py::test_axis[shape109-1] tests/test_univariate.py::test_axis[shape110-2] tests/test_univariate.py::test_axis[shape111-3] tests/test_univariate.py::test_axis[shape112--4] tests/test_univariate.py::test_axis[shape113--3] tests/test_univariate.py::test_axis[shape114--2] tests/test_univariate.py::test_axis[shape115--1] tests/test_univariate.py::test_axis[shape116-0] tests/test_univariate.py::test_axis[shape117-1] tests/test_univariate.py::test_axis[shape118-2] tests/test_univariate.py::test_axis[shape119-3] tests/test_univariate.py::test_axis[shape120--4] tests/test_univariate.py::test_axis[shape121--3] tests/test_univariate.py::test_axis[shape122--2] tests/test_univariate.py::test_axis[shape123--1] tests/test_univariate.py::test_axis[shape124-0] tests/test_univariate.py::test_axis[shape125-1] tests/test_univariate.py::test_axis[shape126-2] tests/test_univariate.py::test_axis[shape127-3] tests/test_univariate.py::test_axis[shape128--4] tests/test_univariate.py::test_axis[shape129--3] tests/test_univariate.py::test_axis[shape130--2] tests/test_univariate.py::test_axis[shape131--1] tests/test_univariate.py::test_axis[shape132-0] tests/test_univariate.py::test_axis[shape133-1] tests/test_univariate.py::test_axis[shape134-2] tests/test_univariate.py::test_axis[shape135-3] tests/test_univariate.py::test_axis[shape136--4] tests/test_univariate.py::test_axis[shape137--3] tests/test_univariate.py::test_axis[shape138--2] tests/test_univariate.py::test_axis[shape139--1] tests/test_univariate.py::test_axis[shape140-0] tests/test_univariate.py::test_axis[shape141-1] tests/test_univariate.py::test_axis[shape142-2] tests/test_univariate.py::test_axis[shape143-3] tests/test_univariate.py::test_axis[shape144--4] tests/test_univariate.py::test_axis[shape145--3] tests/test_univariate.py::test_axis[shape146--2] tests/test_univariate.py::test_axis[shape147--1] tests/test_univariate.py::test_axis[shape148-0] tests/test_univariate.py::test_axis[shape149-1] tests/test_univariate.py::test_axis[shape150-2] tests/test_univariate.py::test_axis[shape151-3] tests/test_univariate.py::test_axis[shape152--4] tests/test_univariate.py::test_axis[shape153--3] tests/test_univariate.py::test_axis[shape154--2] tests/test_univariate.py::test_axis[shape155--1] tests/test_univariate.py::test_axis[shape156-0] tests/test_univariate.py::test_axis[shape157-1] tests/test_univariate.py::test_axis[shape158-2] tests/test_univariate.py::test_axis[shape159-3] tests/test_univariate.py::test_axis[shape160--4] tests/test_univariate.py::test_axis[shape161--3] tests/test_univariate.py::test_axis[shape162--2] tests/test_univariate.py::test_axis[shape163--1] tests/test_univariate.py::test_axis[shape164-0] tests/test_univariate.py::test_axis[shape165-1] tests/test_univariate.py::test_axis[shape166-2] tests/test_univariate.py::test_axis[shape167-3] tests/test_univariate.py::test_axis[shape168--4] tests/test_univariate.py::test_axis[shape169--3] tests/test_univariate.py::test_axis[shape170--2] tests/test_univariate.py::test_axis[shape171--1] tests/test_univariate.py::test_axis[shape172-0] tests/test_univariate.py::test_axis[shape173-1] tests/test_univariate.py::test_axis[shape174-2] tests/test_univariate.py::test_axis[shape175-3] tests/test_univariate.py::test_axis[shape176--4] tests/test_univariate.py::test_axis[shape177--3] tests/test_univariate.py::test_axis[shape178--2] tests/test_univariate.py::test_axis[shape179--1] tests/test_univariate.py::test_axis[shape180-0] tests/test_univariate.py::test_axis[shape181-1] tests/test_univariate.py::test_axis[shape182-2] tests/test_univariate.py::test_axis[shape183-3] tests/test_univariate.py::test_axis[shape184--4] tests/test_univariate.py::test_axis[shape185--3] tests/test_univariate.py::test_axis[shape186--2] tests/test_univariate.py::test_axis[shape187--1] tests/test_univariate.py::test_axis[shape188-0] tests/test_univariate.py::test_axis[shape189-1] tests/test_univariate.py::test_axis[shape190-2] tests/test_univariate.py::test_axis[shape191-3] tests/test_univariate.py::test_axis[shape192--4] tests/test_univariate.py::test_axis[shape193--3] tests/test_univariate.py::test_axis[shape194--2] tests/test_univariate.py::test_axis[shape195--1] tests/test_univariate.py::test_axis[shape196-0] tests/test_univariate.py::test_axis[shape197-1] tests/test_univariate.py::test_axis[shape198-2] tests/test_univariate.py::test_axis[shape199-3] tests/test_univariate.py::test_axis[shape200--4] tests/test_univariate.py::test_axis[shape201--3] tests/test_univariate.py::test_axis[shape202--2] tests/test_univariate.py::test_axis[shape203--1] tests/test_univariate.py::test_axis[shape204-0] tests/test_univariate.py::test_axis[shape205-1] tests/test_univariate.py::test_axis[shape206-2] tests/test_univariate.py::test_axis[shape207-3] tests/test_univariate.py::test_axis[shape208--4] tests/test_univariate.py::test_axis[shape209--3] tests/test_univariate.py::test_axis[shape210--2] tests/test_univariate.py::test_axis[shape211--1] tests/test_univariate.py::test_axis[shape212-0] tests/test_univariate.py::test_axis[shape213-1] tests/test_univariate.py::test_axis[shape214-2] tests/test_univariate.py::test_axis[shape215-3] tests/test_univariate.py::test_axis[shape216--4] tests/test_univariate.py::test_axis[shape217--3] tests/test_univariate.py::test_axis[shape218--2] tests/test_univariate.py::test_axis[shape219--1] tests/test_univariate.py::test_axis[shape220-0] tests/test_univariate.py::test_axis[shape221-1] tests/test_univariate.py::test_axis[shape222-2] tests/test_univariate.py::test_axis[shape223-3] tests/test_univariate.py::test_axis[shape224--4] tests/test_univariate.py::test_axis[shape225--3] tests/test_univariate.py::test_axis[shape226--2] tests/test_univariate.py::test_axis[shape227--1] tests/test_univariate.py::test_axis[shape228-0] tests/test_univariate.py::test_axis[shape229-1] tests/test_univariate.py::test_axis[shape230-2] tests/test_univariate.py::test_axis[shape231-3] tests/test_univariate.py::test_axis[shape232--4] tests/test_univariate.py::test_axis[shape233--3] tests/test_univariate.py::test_axis[shape234--2] tests/test_univariate.py::test_axis[shape235--1] tests/test_univariate.py::test_axis[shape236-0] tests/test_univariate.py::test_axis[shape237-1] tests/test_univariate.py::test_axis[shape238-2] tests/test_univariate.py::test_axis[shape239-3] tests/test_univariate.py::test_zero_smooth tests/test_univariate.py::test_auto_smooth tests/test_univariate.py::test_npoints[x0-y0-xi0-yid0] tests/test_univariate.py::test_npoints[x1-y1-xi1-yid1] tests/test_univariate.py::test_npoints[x2-y2-xi2-yid2] tests/test_univariate.py::test_weighted[w0-yid0]
csaps/__init__.py csaps/_shortcut.py CHANGELOG.md README.md csaps/_version.py csaps/_types.py csaps/_sspumv.py csaps/_sspndg.py
csaps/__init__.py csaps/_shortcut.py CHANGELOG.md README.md csaps/_version.py csaps/_types.py csaps/_sspumv.py csaps/_sspndg.py