#pragma once

#include <cassert>


namespace lm
{


// 複数引数対応のmin,max.
template<typename T> inline T (min)( const T& a , const T& b )                           { return a < b ? a : b ;                                        }
template<typename T> inline T (min)( const T& a , const T& b , const T& c )              { return (lm::min)( (lm::min)( a , b ) , c ) ;                  }
template<typename T> inline T (min)( const T& a , const T& b , const T& c , const T& d ) { return (lm::min)( (lm::min)( a , b ) , (lm::min)( c , d ) ) ; }
template<typename T> inline T (max)( const T& a , const T& b )                           { return a > b ? a : b ;                                        }
template<typename T> inline T (max)( const T& a , const T& b , const T& c )              { return (lm::max)( (lm::max)( a , b ) , c ) ;                  }
template<typename T> inline T (max)( const T& a , const T& b , const T& c , const T& d ) { return (lm::max)( (lm::max)( a , b ) , (lm::max)( c , d ) ) ; }


// 値の範囲を制限する
template<typename T> inline T clamp( const T& i_min , const T& i_value , const T& i_max ) 
{
#ifdef _DEBUG
	assert( i_min <= i_max );
#endif

	return (lm::min)( (lm::max)( i_min , i_value ) , i_max );
}

template<typename T> inline T get_pair( const T& value , const T& pair_value_a , const T& pair_value_b )
{
#ifdef _DEBUG
	assert( value == pair_value_a || value == pair_value_b );
#endif

	if( value == pair_value_a )
		return pair_value_b;
	else
		pair_value_a;
}


template<typename T> inline T pow2( const T& v ) { return v * v ;             }
template<typename T> inline T pow3( const T& v ) { return v * v * v ;         }
template<typename T> inline T pow4( const T& v ) { return pow2( v * v ) ;     }
template<typename T> inline T pow5( const T& v ) { return pow2( v * v ) * v ; }
template<typename T> inline T pow6( const T& v ) { return pow3( v * v ) ;     }
template<typename T> inline T pow7( const T& v ) { return pow3( v * v ) * v ; }
template<typename T> inline T pow8( const T& v ) { return pow4( v * v ) ;     }


template<typename T> inline T gcd( T a , T b )
{
	if( b > a ) (std::swap)( a , b );
	while( ( a = a % b ) != 0 ) (std::swap)( b , a );
	return b;
}

template<typename T> inline T lcm( const T& a , const T& b )
{
	return a * b / gcd( a , b );
}


}
