/*
  ==============================================================================

   This file is part of the JUCE library - "Jules' Utility Class Extensions"
   Copyright 2004-6 by Raw Material Software ltd.

  ------------------------------------------------------------------------------

   JUCE can be redistributed and/or modified under the terms of the
   GNU General Public License, as published by the Free Software Foundation;
   either version 2 of the License, or (at your option) any later version.

   JUCE is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with JUCE; if not, visit www.gnu.org/licenses or write to the
   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
   Boston, MA 02111-1307 USA

  ------------------------------------------------------------------------------

   If you'd like to release a closed-source product which uses JUCE, commercial
   licenses are also available: visit www.rawmaterialsoftware.com/juce for
   more information.

  ==============================================================================
*/

#ifndef __JUCE_MATHSFUNCTIONS_JUCEHEADER__
#define __JUCE_MATHSFUNCTIONS_JUCEHEADER__


//==============================================================================
// Some indispensible min/max functions

/** Returns the larger of two values. */
forcedinline int    jmax (const int a, const int b) throw()                                   { return (a < b) ? b : a; }
/** Returns the larger of two values. */
forcedinline int64  jmax (const int64 a, const int64 b) throw()                               { return (a < b) ? b : a; }
/** Returns the larger of two values. */
forcedinline float  jmax (const float a, const float b) throw()                               { return (a < b) ? b : a; }
/** Returns the larger of two values. */
forcedinline double jmax (const double a, const double b) throw()                             { return (a < b) ? b : a; }

/** Returns the larger of three values. */
inline int    jmax (const int a, const int b, const int c) throw()                            { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); }
/** Returns the larger of three values. */
inline int64  jmax (const int64 a, const int64 b, const int64 c) throw()                      { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); }
/** Returns the larger of three values. */
inline float  jmax (const float a, const float b, const float c) throw()                      { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); }
/** Returns the larger of three values. */
inline double jmax (const double a, const double b, const double c) throw()                   { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); }

/** Returns the larger of four values. */
inline int    jmax (const int a, const int b, const int c, const int d) throw()               { return jmax (a, jmax (b, c, d)); }
/** Returns the larger of four values. */
inline int64  jmax (const int64 a, const int64 b, const int64 c, const int64 d) throw()       { return jmax (a, jmax (b, c, d)); }
/** Returns the larger of four values. */
inline float  jmax (const float a, const float b, const float c, const float d) throw()       { return jmax (a, jmax (b, c, d)); }
/** Returns the larger of four values. */
inline double jmax (const double a, const double b, const double c, const double d) throw()   { return jmax (a, jmax (b, c, d)); }

/** Returns the smaller of two values. */
inline int    jmin (const int a, const int b) throw()                                         { return (a > b) ? b : a; }
/** Returns the smaller of two values. */
inline int64  jmin (const int64 a, const int64 b) throw()                                     { return (a > b) ? b : a; }
/** Returns the smaller of two values. */
inline float  jmin (const float a, const float b) throw()                                     { return (a > b) ? b : a; }
/** Returns the smaller of two values. */
inline double jmin (const double a, const double b) throw()                                   { return (a > b) ? b : a; }

/** Returns the smaller of three values. */
inline int    jmin (const int a, const int b, const int c) throw()                            { return (a > b) ? ((b > c) ? c : b) : ((a > c) ? c : a); }
/** Returns the smaller of three values. */
inline int64  jmin (const int64 a, const int64 b, const int64 c) throw()                      { return (a > b) ? ((b > c) ? c : b) : ((a > c) ? c : a); }
/** Returns the smaller of three values. */
inline float  jmin (const float a, const float b, const float c) throw()                      { return (a > b) ? ((b > c) ? c : b) : ((a > c) ? c : a); }
/** Returns the smaller of three values. */
inline double jmin (const double a, const double b, const double c) throw()                   { return (a > b) ? ((b > c) ? c : b) : ((a > c) ? c : a); }

/** Returns the smaller of four values. */
inline int    jmin (const int a, const int b, const int c, const int d) throw()               { return jmin (a, jmin (b, c, d)); }
/** Returns the smaller of four values. */
inline int64  jmin (const int64 a, const int64 b, const int64 c, const int64 d) throw()       { return jmin (a, jmin (b, c, d)); }
/** Returns the smaller of four values. */
inline float  jmin (const float a, const float b, const float c, const float d) throw()       { return jmin (a, jmin (b, c, d)); }
/** Returns the smaller of four values. */
inline double jmin (const double a, const double b, const double c, const double d) throw()   { return jmin (a, jmin (b, c, d)); }


//==============================================================================
/** Constrains a value to keep it within a given limit.

    Note that this expects that lowerLimit <= upperLimit. If this isn't true,
    the results will be unpredictable.

    @param lowerLimit           the minimum value to return
    @param upperLimit           the maximum value to return
    @param valueToConstrain     the value to try to return
    @returns    the closest value to valueToConstrain which lies between lowerLimit
                and upperLimit (inclusive)
*/
template <class Type>
inline Type jlimit (const Type lowerLimit,
                    const Type upperLimit,
                    const Type valueToConstrain) throw()
{
    jassert (lowerLimit <= upperLimit); // if these are in the wrong order, results are unpredictable..

    return (valueToConstrain < lowerLimit) ? lowerLimit
                                           : ((valueToConstrain > upperLimit) ? upperLimit
                                                                              : valueToConstrain);
}

//==============================================================================
/** Handy function to swap two values over.
*/
template <class Type>
inline void swapVariables (Type& variable1, Type& variable2)
{
    const Type tempVal = variable1;
    variable1 = variable2;
    variable2 = tempVal;
}

//==============================================================================
#ifndef DOXYGEN

#ifdef JUCE_WIN32
  forcedinline double juce_hypot (double a, double b)       { return _hypot (a, b); }
  forcedinline float juce_hypotf (float a, float b)         { return (float) _hypot (a, b); }
#else
  forcedinline double juce_hypot (double a, double b)       { return hypot (a, b); }
  forcedinline float juce_hypotf (float a, float b)         { return hypotf (a, b); }
#endif

inline int64 abs (const int64 n)                            { return (n >= 0) ? n : -n; }

#ifdef __BORLANDC__
  inline float sinf (const float a)                         { return (float) sin (a); }
  inline float cosf (const float a)                         { return (float) cos (a); }
  inline float floorf (const float a)                       { return (float) floor (a); }
  inline float fabsf (const float a)                        { return (float) fabs (a); }
  inline float hypotf (const float a, const float b)        { return (float) hypot (a, b); }
  inline float atan2f (const float a, const float b)        { return (float) atan2 (a, b); }
  inline float sqrtf (const float a)                        { return (float) sqrt (a); }
#endif

#if defined (_MSC_VER) && ! defined (isfinite)
  #define isfinite(a) _finite(a)
#endif


#endif

//==============================================================================
/** A predefined value for Pi, at double-precision.

    @see float_Pi
*/
const double  double_Pi  = 3.1415926535897932384626433832795;

/** A predefined value for Pi, at sngle-precision.

    @see double_Pi
*/
const float   float_Pi   = 3.14159265358979323846f;


//==============================================================================

#endif   // __JUCE_MATHSFUNCTIONS_JUCEHEADER__
