# -*- coding: utf-8 -*-
"""
Limiters for high order DG methods
"""
import numpy as nm

from sfepy.discrete.dg.poly_spaces import iter_by_order
from sfepy.discrete.dg.fields import get_raveler, get_unraveler
from sfepy.base.base import output

MACHINE_EPS = 1e-30


def minmod(a, b, c):
    """Minmod function of three variables, returns:

    0           , where sign(a) != sign(b) != sign(c)

    min(a,b,c)  , elsewhere

    Parameters
    ----------
    a : array_like

    c : array_like

    b : array_like

    Returns
    -------
    out : ndarray
    """
    seq = (nm.sign(a) == nm.sign(b)) & (nm.sign(b) == nm.sign(c))

    res = nm.zeros(nm.shape(a))
    res[seq] = nm.sign(a[seq]) * nm.minimum.reduce([nm.abs(b[seq]),
                                                    nm.abs(a[seq]),
                                                    nm.abs(c[seq])])
    return res


def minmod_seq(abc):
    """Minmod function of n variables, returns:

    0           , where sign(a_1) != sign(a_2) != ... != sign(a_n)

    min(a_1, a_2, a_3, ... , a_n)  , elsewhere

    Parameters
    ----------
    abc : sequence of array_like

    Returns
    -------
    out : ndarray
    """
    seq = nm.hstack([nm.sign(x) for x in abc])
    seq = seq[:, 0, None] == seq
    seq = seq.prod(axis=1).astype(bool)
    res = nm.zeros(nm.shape(abc[0]))
    res[seq] = nm.sign(abc[0][seq]) * \
               nm.minimum.reduce([nm.abs(x[seq]) for x in abc])