//#####################################################################
// Copyright 2002-2006, Ronald Fedkiw, Sergey Koltakov, Eftychios Sifakis.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Function minmax 
//#####################################################################
#ifndef __minmax__
#define __minmax__
#include <algorithm>
#include <cmath>

namespace PhysBAM{
using std::abs;
using std::min;
using std::max;

template<class T>
struct MINMAX_HELPER
{
    T x;
    MINMAX_HELPER operator+(T y) const {return {x<y?y:x};}
    MINMAX_HELPER operator-(T y) const {return {x<y?x:y};}
    MINMAX_HELPER operator*(T y) const {return {abs(x)<abs(y)?y:x};}
    MINMAX_HELPER operator/(T y) const {return {abs(x)<abs(y)?x:y};}
};

template<class T>
constexpr inline T min(T a)
{return a;};

template<class T>
constexpr inline T max(T a)
{return a;};

template<class T,class ...Args>
constexpr inline T min(T a,T b,T c,Args&&... d)
{return ((MINMAX_HELPER<T>{a}-b-c)-...-d).x;}

template<class T,class ...Args>
constexpr inline T max(T a,T b,T c,Args&&... d)
{return ((MINMAX_HELPER<T>{a}+b+c)+...+d).x;}

template<class T,class ...Args>
constexpr inline T minabs(T a,Args&&... d)
{return (MINMAX_HELPER<T>{abs(a)}-...-abs(d)).x;}

template<class T,class ...Args>
constexpr inline T maxabs(T a,Args&&... d)
{return (MINMAX_HELPER<T>{abs(a)}+...+abs(d)).x;}

template<class T,class ...Args>
constexpr inline T minmag(T a,Args&&... d)
{return (MINMAX_HELPER<T>{a}/.../d).x;}

template<class T,class ...Args>
constexpr inline T maxmag(T a,Args&&... d)
{return (MINMAX_HELPER<T>{a}*...*d).x;}

}
#endif
