// WINMAX.H - max() and min() functions for C++ DOS and Windows programs.
// Uploaded by Dan O'Connor (71161,1517) for the benefit of everyone!

//     Those who have tried to compile the examples from Charles Petzold's
//  "Programming Windows, 2ed." using C++ have discovered that the max()
//  and min() macros are excluded when compiling under C++.  This is done
//  on purpose to allow C++ classes to define their own max() and min()
//  member functions.  The presence of the macros defeates C++'s ability
//  to overload these functions, since the preprocessor gets to them first!
//
//     The answer, in accordance with ARM Sec. 16.1c, is to use overloaded
//  inline functions.  Inline functions will produce the same code as the
//  macro,  but the use of inline functions has two additional benefits:
//  (1) the linker can enforce type-safe linkage; this is not possible with
//  preprocessor macros; and (2) inline functions allow overloading, thus max()
//  and min() will not collide with classes that also define max() and min().
//
//     This header defines four inline functions: max(), min(), absMax(), and
//   absMin().  The purpose of each is described below:
//
//   max()      Returns the argument with the larger value.
//   min()      Returns the argument with the smaller value.
//   absMax()   Returns the argument with the larger absolute value (magnitude).
//   absMin()   Returns the argument with the smaller absolute value.
//
//     Each function is overloaded for four data types, int, long int, float,
//   and double.  If there are other data types you need, such as char, unsigned
//   int, etc., feel free to add it!  Overloading is good for the soul!  Keep in
//   mind that absMax() and absMin() need not be defined for unsigned types,
//   since unsigned types are, by definition, positive numbers.
//
//     It is my hope that these functions will help eliminate the confusion
//   inherent with trying to use the max() and min() macros under C++.
//
//   Good luck to all,
//     Dan O'Connor
//     71161,1517


#ifndef WINMAX_H       // Only include once!
#define WINMAX_H       // Define name on first pass thru!

#ifndef __cplusplus
#error WINMAX Requires C++ to Compile        // Oops! Overloading requires C++.
#endif

#include <math.h>      // Needed for absolute value functions.

// --- max() functions ---
inline int    max(int x, int y)  { return ( x > y ? x : y ); }
inline long   max(long x, long y)  { return ( x > y ? x : y ); }
inline int    max(float x, float y)  { return ( x > y ? x : y ); }
inline double max(double x, double y)  { return ( x > y ? x : y ); }

// --- min() functions ---
inline int    min(int x, int y)  { return ( x < y ? x : y ); }
inline long   min(long x, long y)  { return ( x < y ? x : y ); }
inline float  min(float x, float y)  { return ( x < y ? x : y ); }
inline double min(double x, double y)  { return ( x < y ? x : y ); }

// --- absMax() functions ---
inline int    absMax(int x, int y) { return ( abs(x) > abs(y) ? x : y ); }
inline long   absMax(long x, long y) { return ( labs(x) > labs(y) ? x : y ); }
inline float  absMax(float x, float y) { return (fabs(x) > fabs(y) ? x : y); }
inline double absMax(double x, double y) { return (fabs(x) > fabs(y) ? x : y); }

// --- absMin() functions ---
inline int    absMin(int x, int y) { return (abs(x) < abs(y) ? x : y); }
inline long   absMin(long x, long y) { return (labs(x) < labs(y) ? x : y); }
inline float  absMin(float x, float y) { return (fabs(x) < fabs(y) ? x : y); }
inline double absMin(double x, double y) { return (fabs(x) < fabs(y) ? x : y); }

#endif
