<commit_before>from __future__ import division, print_function, absolute_import
import numpy as np


class OdeSolver(object):
    """Base class for ODE solvers.

    In order to implement a new solver you need to follow the guidelines:

        1. A constructor must accept parameters presented in the base class
           (listed below) followed by any other parameters specific to a
           solver.
        2. A solver must implement a private method
           `_step_impl(self, max_step=np.inf)` which propagates a solver one
           step further. It must return tuple ``(success, message)``, where
           ``success`` is a boolean indicating whether a step was successful,
           and ``message`` is a string containing description of a failure if
           a step failed or None otherwise.
        3. A solver must implement a private method `_dense_output_impl(self)`
           which returns `DenseOutput` object covering the last successful
           step.
        4. A solver must have attributes listed below in Attributes section.

    Parameters
    ----------
    fun : callable
        Right-hand side of the system. The calling signature is ``fun(t, y)``.
        Here ``t`` is a scalar, and ``y`` is ndarray with shape (n,). It
        must return an array_like with shape (n,).
    t0 : float
        Initial time.
    y0 : array_like, shape (n,)
        Initial state.
    t_crit : float
        Boundary time --- the integration won't continue beyond it. It also
        determines the direction of the integration.

    Attributes
    ----------
    n : int
        Number of equations.
    status : string
        Current status of the solver: 'running', 'finished' or 'failed'.
    t_crit : float
        Boundary time.
    direction : float
        Integration direction: +1 or -1.
    t : float
        Current time.
    y : ndarray
        Current state.
    step_size : float
        Size of the last successful step. None if no steps were made yet.
    """
    TOO_SMALL_STEP = "Required step size is less than spacing between numbers."

    def __init__(self, fun, t0, y0, t_crit):
        def fun_wrapped(t, y):
            return np.atleast_1d(fun(t, y))

        self.fun = fun_wrapped
        self.t = t0
        self.y = np.asarray(y0)
        self.t_crit = t_crit

        if self.t == self.t_crit:
            raise ValueError("Initial `t` coincides with `t_crit`.")

        self.direction = np.sign(t_crit - t0)
        self.n = self.y.shape[0]
        self.status = 'running'
        self.step_size = None

    def step(self, max_step=np.inf):
        """Perform one integration step.

        Parameters
        ----------
        max_step : float, optional
            Maximum allowed step size. Default is np.inf, i.e. the step is not
            bounded and determined solely by the solver.

        Returns
        -------
        message : string or None
            Report from the solver. Typically a reason for failure if
            `solve.status` is 'failed' after the step was taken or None<commit_msg>MAINT: Refactor out arguments checking in OdeSolver<commit_after>from __future__ import division, print_function, absolute_import
import numpy as np


def check_arguments(fun, y0):
    y0 = np.asarray(y0, dtype=float)

    if y0.ndim != 1:
        raise ValueError("`y0` must be 1-dimensional.")

    def fun_wrapped(t, y):
        return np.asarray(fun(t, y))

    return fun_wrapped, y0


class OdeSolver(object):
    """Base class for ODE solvers.

    In order to implement a new solver you need to follow the guidelines:

        1. A constructor must accept parameters presented in the base class
           (listed below) followed by any other parameters specific to a
           solver.
        2. A solver must implement a private method
           `_step_impl(self, max_step=np.inf)` which propagates a solver one
           step further. It must return tuple ``(success, message)``, where
           ``success`` is a boolean indicating whether a step was successful,
           and ``message`` is a string containing description of a failure if
           a step failed or None otherwise.
        3. A solver must implement a private method `_dense_output_impl(self)`
           which returns `DenseOutput` object covering the last successful
           step.
        4. A solver must have attributes listed below in Attributes section.

    Parameters
    ----------
    fun : callable
        Right-hand side of the system. The calling signature is ``fun(t, y)``.
        Here ``t`` is a scalar, and ``y`` is ndarray with shape (n,). It
        must return an array_like with shape (n,).
    t0 : float
        Initial time.
    y0 : array_like, shape (n,)
        Initial state.
    t_crit : float
        Boundary time --- the integration won't continue beyond it. It also
        determines the direction of the integration.

    Attributes
    ----------
    n : int
        Number of equations.
    status : string
        Current status of the solver: 'running', 'finished' or 'failed'.
    t_crit : float
        Boundary time.
    direction : float
        Integration direction: +1 or -1.
    t : float
        Current time.
    y : ndarray
        Current state.
    step_size : float
        Size of the last successful step. None if no steps were made yet.
    """
    TOO_SMALL_STEP = "Required step size is less than spacing between numbers."

    def __init__(self, fun, t0, y0, t_crit):
        self.t = t0
        self.fun, self.y = check_arguments(fun, y0)
        self.t_crit = t_crit

        if self.t == self.t_crit:
            raise ValueError("Initial `t` coincides with `t_crit`.")

        self.direction = np.sign(t_crit - t0)
        self.n = self.y.shape[0]
        self.status = 'running'
        self.step_size = None

    def step(self, max_step=np.inf):
        """Perform one integration step.

        Parameters
        ----------
        max_step : float, optional
            Maximum allowed step size. Default is np.inf, i.e. the step is not
            bounded and determined solely by the solver.

        Returns
        -------
        message : string or None
            Report from the solver. Typically a reason for failure if
            `solve.status` is 'failed' after the step was taken or None
{'fraction_non_alphanumeric': 0.08345187292555714, 'fraction_numerical': 0.005847953216374269, 'mean_word_length': 2.045235803657363, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2616244', 'n_tokens_mistral': 1748, 'n_tokens_neox': 1686, 'n_words': 718}