import math


def descent_step(position, obj_at_pos, function, grad_function, step_size):
    """Do a small step in the direction of steepest descent.

    Parameters
    ----------
    position : list
        The current incumbent solution.
    obj_at_pos : float
        The objective value at this position (to save one evaluation).
    function : callable
        The objective function.
    grad_function : callable
        A function returning the gradient.
    step_size : float
        Step size for each dimension.

    Returns
    -------
    proposed_point : list
        A point which is hopefully an improvement.
    norm : float
        The length of the gradient vector (useful as stopping criterion).

    """
    gradient = grad_function(position, obj_at_pos, function, step_size)
    norm = math.sqrt(math.fsum(g ** 2 for g in gradient))
    step_vector = [step_size * g / norm for g in gradient]
    proposed_point = [p - s for p, s in zip(position, step_vector)]
    return proposed_point, norm