# Path: scvelo/core/_arithmetic.py
# def prod_sum(
#     a1: Union[ndarray, spmatrix], a2: Union[ndarray, spmatrix], axis: Optional[int]
# ) -> ndarray:
#     """Take sum of product of two arrays along given axis.
# 
#     Arguments
#     ---------
#     a1
#         First array.
#     a2
#         Second array.
#     axis
#         Axis along which to sum elements. If `None`, all elements will be summed.
#         Defaults to `None`.
# 
#     Returns
#     -------
#     ndarray
#         Sum of product of arrays along given axis.
#     """
# 
#     if issparse(a1):
#         return a1.multiply(a2).sum(axis=axis).A1
#     elif axis == 0:
#         return np.einsum("ij, ij -> j", a1, a2) if a1.ndim > 1 else (a1 * a2).sum()
#     elif axis == 1:
#         return np.einsum("ij, ij -> i", a1, a2) if a1.ndim > 1 else (a1 * a2).sum()
# 
# def sum(a: Union[ndarray, spmatrix], axis: Optional[int] = None) -> ndarray:
#     """Sum array elements over a given axis.
# 
#     Arguments
#     ---------
#     a
#         Elements to sum.
#     axis
#         Axis along which to sum elements. If `None`, all elements will be summed.
#         Defaults to `None`.
# 
#     Returns
#     -------
#     ndarray
#         Sum of array along given axis.
#     """
# 
#     if a.ndim == 1:
#         axis = 0
# 
#     with warnings.catch_warnings():
#         warnings.simplefilter("ignore")
#         return a.sum(axis=axis).A1 if issparse(a) else a.sum(axis=axis)


from typing import List, Optional, Tuple, Union
from numpy import ndarray
from scipy.sparse import csr_matrix, issparse
from ._arithmetic import prod_sum, sum
import numpy as np

        return [trimmer.getnnz(axis=0)] + [
            trimmer.multiply(data_mat).tocsr() for data_mat in data
        ]

    def fit(self, x: ndarray, y: ndarray):
        """Fit linear model per column.

        Arguments
        ---------
        x
            Training data of shape `(n_obs, n_vars)`.
        y
            Target values of shape `(n_obs, n_vars)`.

        Returns
        -------
        self
            Returns an instance of self.
        """

        n_obs = x.shape[0]

        if self.percentile is not None:
            n_obs, x, y = self._trim_data(data=[x, y])

        _xx = prod_sum(x, x, axis=0)
        _xy = prod_sum(x, y, axis=0)

        if self.fit_intercept:

# Path: scvelo/core/_arithmetic.py
# def prod_sum(
#     a1: Union[ndarray, spmatrix], a2: Union[ndarray, spmatrix], axis: Optional[int]
# ) -> ndarray:
#     """Take sum of product of two arrays along given axis.
# 
#     Arguments
#     ---------
#     a1
#         First array.
#     a2
#         Second array.
#     axis
#         Axis along which to sum elements. If `None`, all elements will be summed.
#         Defaults to `None`.
# 
#     Returns
#     -------
#     ndarray
#         Sum of product of arrays along given axis.
#     """
# 
#     if issparse(a1):
#         return a1.multiply(a2).sum(axis=axis).A1
#     elif axis == 0:
#         return np.einsum("ij, ij -> j", a1, a2) if a1.ndim > 1 else (a1 * a2).sum()
#     elif axis == 1:
#         return np.einsum("ij, ij -> i", a1, a2) if a1.ndim > 1 else (a1 * a2).sum()
# 
# def sum(a: Union[ndarray, spmatrix], axis: Optional[int] = None) -> ndarray:
#     """Sum array elements over a given axis.
# 
#     Arguments
#     ---------
#     a
#         Elements to sum.
#     axis
#         Axis along which to sum elements. If `None`, all elements will be summed.
#         Defaults to `None`.
# 
#     Returns
#     -------
#     ndarray
#         Sum of array along given axis.
#     """
# 
#     if a.ndim == 1:
#         axis = 0
# 
#     with warnings.catch_warnings():
#         warnings.simplefilter("ignore")
#         return a.sum(axis=axis).A1 if issparse(a) else a.sum(axis=axis)


# Path: scvelo/core/_linear_models.py
from typing import List, Optional, Tuple, Union
from numpy import ndarray
from scipy.sparse import csr_matrix, issparse
from ._arithmetic import prod_sum, sum
import numpy as np


        return [trimmer.getnnz(axis=0)] + [
            trimmer.multiply(data_mat).tocsr() for data_mat in data
        ]

    def fit(self, x: ndarray, y: ndarray):
        """Fit linear model per column.

        Arguments
        ---------
        x
            Training data of shape `(n_obs, n_vars)`.
        y
            Target values of shape `(n_obs, n_vars)`.

        Returns
        -------
        self
            Returns an instance of self.
        """

        n_obs = x.shape[0]

        if self.percentile is not None:
            n_obs, x, y = self._trim_data(data=[x, y])

        _xx = prod_sum(x, x, axis=0)
        _xy = prod_sum(x, y, axis=0)

        if self.fit_intercept:

            _x = sum(x, axis=0) / n_obs