// Aqsis
// Copyright (c) 1997 - 2001, Paul C. Gregory
//
// Contact: pgregory@aqsis.com
//
// This library 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 library 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 library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/**
 * Copyright (C) 2006-2007  NTT DATA CORPORATION
 * 
 * Version: 1.0.0 2007/04/01
 *  
 */
package net.cellcomputing.himawari.library.types;

import static java.lang.Math.min;
import static java.lang.Math.max;

/**
 * 
 * このパッケージで利用されるグローバル関数
 * 
 * @author NTT DATA Corporation
 */
public strictfp class PublicFunctions {
	
	
	/**
	 * ２点間を線形に t:1-t に内分する点を求める. <br>
	 * Linearly interpolate between the two given values to the point t, 0<=t<=1.
	 * 
	 * @param t	内分比率（0<=t<=1）
	 * @param x0	点１
	 * @param x1	点２
	 * @return	２点間を線形に内分する点
	 */
	public static final float LERP( float t, float x0, float x1 ){
		return ( (x0) + (t)*((x1)-(x0)) );
	}
	
	/**
	 * 与えられた値を、指定した範囲に収まるようにする。<br>
	 * Clamp the given value a, to be with the extents of the given range.
	 * 
	 * @param a	範囲に収めたい値
	 * @param min	範囲の下限
	 * @param max	範囲の上限
	 * @return	指定した範囲を超えない値
	 */
	public static final float CLAMP( float a, float min, float max ){
		return ( a<min? min : ( a>max? max:a ) ); 
	}
	
	/**
	 * CqColorオブジェクトに対するmin演算。<br>
	 * 各要素ごとに小さい方の値が採用された、新しいCqColorオブジェクトを返す。<br>
	 * Determine the minimum of the two colors given.
	 * 
	 * @param a	CqColorオブジェクト１
	 * @param b	CqColorオブジェクト２
	 * @return	各要素ごとに小さい方の値が採用された新しいCqColorオブジェクト
	 */
	public static final CqColor CMIN( CqColor a, CqColor b ){
		return new CqColor( min(a.fRed(), b.fRed()), min(a.fGreen(), b.fGreen()), min(a.fBlue(), b.fBlue()) );
	}
	
	/**
	 * CqColorオブジェクトに対するmax演算。<br>
	 * 各要素ごとに大きい方の値が採用された、新しいCqColorオブジェクトを返す。<br>
	 * Determine the maximum of the two colors given.
	 * 
	 * @param a	CqColorオブジェクト１
	 * @param b	CqColorオブジェクト２
	 * @return	各要素ごとに大きい方の値が採用された新しいCqColorオブジェクト
	 */
	public static final CqColor CMAX( CqColor a, CqColor b ){
		return new CqColor( max(a.fRed(), b.fRed()), max(a.fGreen(), b.fGreen()), max(a.fBlue(), b.fBlue()) );
	}
	
	/**
	 * CqColorオブジェクトに対するclamp演算。<br>
	 * 各要素ごとに指定範囲を超えないような値が採用された、新しいCqColorオブジェクトを返す。<br>
	 * Clamp the given color a, to be with the extents of the given range.
	 * 
	 * @param a	指定範囲に収めたいCqColor
	 * @param min	範囲の下限
	 * @param max	範囲の上限
	 * @return	各要素ごとに指定範囲を超えないような値が採用された新しいCqColorオブジェクト
	 */
	public static final CqColor CCLAMP( CqColor a, CqColor min, CqColor max ){
		return new CqColor( CLAMP(a.fRed(), min.fRed(), max.fRed()), CLAMP(a.fGreen(), min.fGreen(), max.fGreen()), CLAMP(a.fBlue(), min.fBlue(), max.fBlue()) );
	}
	
	/**
	 * CqVector3Dオブジェクトに対するmin演算。<br>
	 * 各要素ごとに小さい方の値が採用された、新しいCqVector3Dオブジェクトを返す。<br>
	 * Determine the minimum of the two vectors given.
	 * 
	 * @param a	CqVector3Dオブジェクト１
	 * @param b	CqVector3Dオブジェクト２
	 * @return	各要素ごとに小さい方の値が採用された新しいCqVector3Dオブジェクト
	 */
	public static final CqVector3D VMIN( CqVector3D a, CqVector3D b ){
		return new CqVector3D( min(a.x, b.x), min(a.y, b.y), min(a.z, b.z) );
	}
	
	/**
	 * CqVector3Dオブジェクトに対するmax演算。<br>
	 * 各要素ごとに大きい方の値が採用された、新しいCqVector3Dオブジェクトを返す。<br>
	 * Determine the maximum of the two vectors given.
	 * 
	 * @param a	CqVector3Dオブジェクト１
	 * @param b	CqVector3Dオブジェクト２
	 * @return	各要素ごとに大きい方の値が採用された新しいCqVector3Dオブジェクト
	 */
	public static final CqVector3D VMAX( CqVector3D a, CqVector3D b ){
		return new CqVector3D( max(a.x, b.x), max(a.y, b.y), max(a.z, b.z) );
	}
	
	/// Clamp the given vector a, to be with the extents of the given range.
	/**
	 * CqVector3Dオブジェクトに対するclamp演算。<br>
	 * 各要素ごとに指定範囲を超えないような値が採用された、新しいCqVector3Dオブジェクトを返す。<br>
	 * Clamp the given vector a, to be with the extents of the given range.
	 * 
	 * @param a	指定範囲に収めたいCqVector3D
	 * @param min	範囲の下限
	 * @param max	範囲の上限
	 * @return	各要素ごとに指定範囲を超えないような値が採用された新しいCqVector3Dオブジェクト
	 */
	public static final CqVector3D VCLAMP( CqVector3D a, CqVector3D min, CqVector3D max ){
		return new CqVector3D( CLAMP( a.x, min.x, max.x ), CLAMP( a.y, min.y, max.y ), CLAMP( a.z, min.z, max.z ) );
	}
	
	/**
	 * 引数をビット化したとき、一番右端の１の位置を求める（最低ビットの計算）.<br>
	 * Determine the lowest set bit in an unsigned value.
	 * 
	 * @param x	任意の整数値
	 * @return	一番右側のビットを表わすint値（2~n）
	 */
	public static final long LOWEST_BIT( long x )
	{
		return ( x & ( ( ~x ) + 1 ) );
	}
	
	/**
	 * 引数が２のべき乗かどうか。<br>
	 * Determine if the given value is a power of two.
	 * 
	 * @param x	任意の整数値
	 * @return	true: べき乗　false: べき乗でない
	 */
	public static final boolean IS_POW2( long x )
	{
		return ( x != 0 && x == LOWEST_BIT( x ) );
	}
	
	/**
	 * 引数の最高ビット以下のビットをすべて立てる。即ち、n桁目が最高ビットであれば、2^n-1を計算する（2^n-1の世界での切り上げ）.<br>
	 * Calculate the next highest power of two minus 1 from the given value.
	 * 
	 * @param x	任意の整数値
	 * @return	2^n-1の世界での切り上げ値
	 */
	public static final long CEIL_POW2_MINUS1( long x )
	{
		for ( long i = 1; i!=0; i <<= 1 ){
			x |= x >> i;
		}
		return ( x );
	}
	
	/**
	 * 引数の最高ビットの１つ左のビット値を算出。即ち、n桁目が最高ビットであれば、2^nを計算する（２のべき乗の世界での切り上げ）.<br>
	 * ただし、引数が2^nのときはそのまま2^nが返る（ようだ）<br>
	 * Calculate the next highest power of two from the given value.
	 * 
	 * @param x	任意の整数値
	 * @return	２のべき乗の世界での切り上げ値
	 */
	public static final long CEIL_POW2( long x )
	{
		return ( CEIL_POW2_MINUS1( x - 1 ) + 1 );
	}
	
	public static final float RAD(float a)
	{
		return (float) ((a)/(180.0f/Math.PI)) ;
	}
//	/ Convert the given radians value to degrees.
	public static final float DEG(float a)
	{
		return (float) ((a)/(Math.PI/180.0f));
	}
}
