// Numeric.h - numerical utility functions.
//
//	Vamos Automotive Simulator
//  Copyright (C) 2005 Sam Varner
//
//  This program is free software; you can redistribute it and/or modify
//  it 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.
//
//  This program 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 this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#ifndef _NUMERIC_H_
#define _NUMERIC_H_

#include "Constants.h"

#include <algorithm>

// Windows' normal build config defines these as macros.
// Undefine these to get real std::min() and std::max() usuable.
#ifdef WIN32
# undef min
# undef max
#endif

namespace Vamos_Geometry
{
  // Return -1, 0, 1 for VALUE < 0, == 0, > 0, respectively.
  template <typename T> T  sign (T value)
  { return value == 0 ? 0 : (value > 0 ? 1 : -1); }

  // Clip VALUE to the range LOW--HIGH.
  template <typename T> T clip (T value, T low, T high)
  { return std::max (std::min (value, high), low); }

  // True if VALUE is in the range LOW--HIGH.
  template <typename T> bool is_in_range (T value, T low, T high)
  { return (value >= low) && (value <= high); }

  // Return LOW or HIGH, whichever is closer to VALUE.
  template <typename T> T closer (T value, T low, T  high)
  { return (std::abs (value - low) < std::abs (value - high)) ? low : high; }

  // Return angle in the interval [minimum, minimum + 2pi).
  template <typename T> T branch (T angle, T minimum)
  {
    while (angle > minimum + 2*pi)
      angle -= 2*pi;
    while (angle <= minimum)
      angle += 2*pi;
    return angle;
  }

  // Square a number
  template <typename T> T  square (T value)
  { return value * value; }

  // Cube a number
  template <typename T> T  cube (T value)
  { return value * value * value; }

  // Return f(X0) for a line with SLOPE through (X1, Y1).
  template <typename T> T intercept (T x0, T x1, T y1, T slope)
  { return y1 - slope * (x1 - x0); } 

  template <typename T> T interpolate (T x, T x1, T y1, T x2, T y2)
  { return y1 + (y2 - y1) * (x - x1) / (x2 - x1); }
}

#endif
