// 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.max;
import static java.lang.Math.min;
import static java.lang.Math.abs;
import net.cellcomputing.himawari.accessory.primitive.p_float;


/**
 * 
 * RGBの色情報を保持するクラス。
 * 
 * @author NTT DATA Corporation
 */
public strictfp class CqColor {

	public float	m_fRed,     ///< the red component 0.0-1.0
				    m_fGreen,   ///< the green component 0.0-1.0
				    m_fBlue;	///< the blue component 0.0-1.0
	
	
	private static final float UNDEFINED = -1;
    private static final float Small_Value = 0.0000001f;
    
    private static final CqMatrix matRGBtoYIQ1
								= new CqMatrix(	0.299f,  0.587f,  0.114f, 0.0f,
									    		0.596f, -0.274f, -0.322f, 0.0f,
									    		0.212f, -0.523f,  0.311f, 0.0f,
									    		  0.0f,    0.0f,    0.0f, 1.0f );

    private static final  CqMatrix matRGBtoYIQ2
								= new CqMatrix(	1.0f,  0.956f,  0.621f, 0.0f,
												1.0f, -0.272f, -0.647f, 0.0f,
												1.0f, -1.105f,  1.702f, 0.0f,
												0.0f,    0.0f,    0.0f, 1.0f );
	
	
	//************************************************************************//
	//*** コンストラクタの定義
	//************************************************************************//
	
	/**
	 * 全要素を０で初期化する
	 */
	public CqColor(){
		this.m_fRed		= 0.0f;
		this.m_fGreen	= 0.0f;
		this.m_fBlue	= 0.0f;
	}
	
	/**
	 * RGBをそれぞれ指定して初期化する
	 * @param fRed		赤を示すfloat値（0.0〜1.0）
	 * @param fGreen	緑を示すfloat値（0.0〜1.0）
	 * @param fBlue	青を示すfloat値（0.0〜1.0）
	 */
	public CqColor( float fRed, float fGreen, float fBlue ){
		this.m_fRed		= fRed;
		this.m_fGreen	= fGreen;
		this.m_fBlue	= fBlue;
	}
	
	/**
	 * RGBをそれぞれｆで初期化する
	 * @param f	色を示すfloat値（0.0〜1.0）
	 */
	public CqColor( float f ){
		this.m_fRed		= f;
		this.m_fGreen	= f;
		this.m_fBlue	= f;
	}
	
	/**
	 * ３次元ベクトルをRGB色空間と見なして初期化する
	 * @param From	RGBを表わす３次元ベクトル
	 */
	public CqColor( final CqVector3D From ){
		this.m_fRed		= From.x;
		this.m_fGreen	= From.y;
		this.m_fBlue	= From.z;
	}
	
	/**
	 * RGBを表わすfloat[3]配列で初期化する
	 * @param From	RGBを表わすfloat[3]配列
	 */
	public CqColor( final float From[] ){
		this.m_fRed		= From[ 0 ];
		this.m_fGreen	= From[ 1 ];
		this.m_fBlue	= From[ 2 ];
	}
	
	/**
	 * コピーコンストラクタ
	 * @param from	コピー元
	 */
	public CqColor( final CqColor From ){
//		this.assignment( From );
		m_fRed = From.m_fRed;
		m_fGreen = From.m_fGreen;
		m_fBlue = From.m_fBlue;
		
	}
	
	//************************************************************************//
	//*** メソッドの定義
	//************************************************************************//
	
	/**
	 * REDのゲッタ。
	 * @return	赤を示すfloat値（0.0〜1.0）
	 */
	public float fRed(){
		return m_fRed;
	}
	
	/**
	 * GREENのゲッタ。
	 * @return	緑を示すfloat値（0.0〜1.0）
	 */
	public float fGreen(){
		return m_fGreen;
	}
	
	/**
	 * BLUEのゲッタ。
	 * @return	青を示すfloat値（0.0〜1.0）
	 */
	public float fBlue(){
		return m_fBlue;
	}
	
	/**
	 * REDのセッタ。
	 * @param fRed	赤を示すfloat値（0.0〜1.0）
	 */
	public void SetfRed( final float fRed ){
		this.m_fRed = fRed;
	}
	
	/**
	 * GREENのセッタ。
	 * @param fGreen	緑を示すfloat値（0.0〜1.0）
	 */
	public void SetfGreen( final float fGreen ){
		this.m_fGreen = fGreen;
	}
	
	/**
	 * BLUEのセッタ。
	 * @param fBlue	青を示すfloat値（0.0〜1.0）
	 */
	public void SetfBlue( final float fBlue ){
		this.m_fBlue = fBlue;
	}
	
	/**
	 * RGBのゲッタ。 <br>
	 * 引数に対してそれぞれRGBを返す。
	 * 
	 * @param pfRed	赤を示すfloat値（0.0〜1.0）
	 * @param pfGreen	緑を示すfloat値（0.0〜1.0）
	 * @param pfBlue	青を示すfloat値（0.0〜1.0）
	 */
	public void GetColorRGB( p_float pfRed, p_float pfGreen, p_float pfBlue ){
		pfRed.value		= m_fRed;
		pfGreen.value	= m_fGreen;
		pfBlue.value	= m_fBlue;
	}
	
	/**
	 * RGBのセッタ。 <br>
	 * 
	 * @param fRed	赤を示すfloat値（0.0〜1.0）
	 * @param fGreen	緑を示すfloat値（0.0〜1.0）
	 * @param fBlue	青を示すfloat値（0.0〜1.0）
	 */
	public void SetColorRGB( float fRed, float fGreen, float fBlue ){
		m_fRed		= fRed;
		m_fGreen	= fGreen;
		m_fBlue		= fBlue;
	}
	
	/**
	 * 0.0〜1.0の範囲に収める
	 */
	public void Clamp(){
        if ( m_fRed   > 1.0 ){	m_fRed   = 1.0f; }
        if ( m_fGreen > 1.0 ){	m_fGreen = 1.0f; }
        if ( m_fBlue  > 1.0 ){	m_fBlue  = 1.0f; }

        if ( m_fRed   < 0.0 ){	m_fRed   = 0.0f; }
        if ( m_fGreen < 0.0 ){	m_fGreen = 0.0f; }
        if ( m_fBlue  < 0.0 ){	m_fBlue  = 0.0f; }
	}
	
	
    /**
     * ＲＧＢ→ＨＳＶ変換
     * 
     * @return	このCqColorをHSV変換した、新しいCqColorオブジェクト
     */
    public CqColor	rgbtohsv(){

        float R = m_fRed, G = m_fGreen, B = m_fBlue;
        float H = UNDEFINED, S, V;
        // RGB_TO_HSV from Foley, van Dam, Feiner, Hughes 2nd Ed. Pg 592
        float max = max( m_fRed, m_fGreen );	max = max( max, m_fBlue );
        float min = min( m_fRed, m_fGreen );	min = min( min, m_fBlue );
        float diff = max - min;

        V = max;

        // Next Saturation
        if ( max != 0.0f ) S = diff / max;
        else	S = 0.0f;

        // Next Hue
        if ( S == 0.0f ) H = UNDEFINED;	// UNDEFINED
        else
        {
            float r_dist = ( max - R ) / diff;
            float g_dist = ( max - G ) / diff;
            float b_dist = ( max - B ) / diff;

            if ( R == max ) H = b_dist - g_dist;
            else if ( G == max ) H = 2.0f + r_dist - b_dist;
            else if ( B == max ) H = 4.0f + g_dist - r_dist;

            H *= 60;
            if ( H < 0 ) H += 360;
        }

        return ( new CqColor( H / 360.0f, S, V ) );
    	
    }
	
    /**
     * ＲＧＢ→ＨＳＬ変換
     * 
     * @return	このCqColorをHSL変換した、新しいCqColorオブジェクト
     */
    public CqColor	rgbtohsl(){

    	    float H = UNDEFINED, S = 0.0f, L;
    	    float R = m_fRed, G = m_fGreen, B = m_fBlue;
    	    // RGB_TO_HLS from Foley, van Dam, Feiner, Hughes 2nd Ed. Pg 595
    	    float max = max( R, G );	max = max( max, B );
    	    float min = min( R, G );	min = min( min, B );
    	    float diff = max - min;

    	    L = ( max + min ) / 2;

    	    // Next Saturation
    	    if ( abs( diff ) <= Small_Value )
    	    {
    	        L = 0.0f;
    	        H = UNDEFINED;
    	    }
    	    else
    	    {
    	        if ( L < 0.5f ) S = diff / ( max + min );
    	        else	S = diff / ( 2.0f - max - min );

    	        float r_dist = ( max - R ) / diff;
    	        float g_dist = ( max - G ) / diff;
    	        float b_dist = ( max - B ) / diff;

    	        // Next Hue
    	        if ( R == max ) H = b_dist - g_dist;
    	        else if ( G == max ) H = 2.0f + r_dist - b_dist;
    	        else if ( B == max ) H = 4.0f + g_dist - r_dist;

    	        H *= 60;
    	        if ( H < 0 ) H += 360;
    	    }

    	    return ( new CqColor( H / 360.0f, S, L ) );
    }
	
    /**
     * ＲＧＢ→ＸＹＺ変換
     * 
     * @return	このCqColorをXYZ変換した、新しいCqColorオブジェクト
     */
    public CqColor	rgbtoXYZ(){
        CqColor c = new CqColor( m_fRed, m_fGreen, m_fBlue );
        return c;
    }
	
    /**
     * ＲＧＢ→xyY変換
     * 
     * @return	このCqColorをxyY変換した、新しいCqColorオブジェクト
     */
    public CqColor	rgbtoxyY(){
        CqColor c = new CqColor( m_fRed, m_fGreen, m_fBlue );
        return c;
    }
    
    /**
     * ＲＧＢ→YIQ変換
     * 
     * @return	このCqColorをYIQ変換した、新しいCqColorオブジェクト
     */
    public CqColor	rgbtoYIQ(){
    	
    	CqColor c = new CqColor( matRGBtoYIQ1.multiply( new CqVector3D( m_fRed, m_fGreen, m_fBlue ) ) );
    	
    	return ( c );
    }
    
    /**
     * ＨＳＶ→ＲＧＢ変換
     * 
     * @return	このCqColorをRGB変換した、新しいCqColorオブジェクト
     */
    public CqColor	hsvtorgb(){	
    	
        float H = m_fRed * 360.0f, S = m_fGreen, V = m_fBlue;
        float R = 0.0f, G = 0.0f, B = 0.0f;
        // HSV_TO_RGB from Foley, van Dam, Feiner, Hughes 2nd Ed. Pg 593
        if ( S == 0.0 )
        {
            assert( H < 0 );	// If s==0 then h MUST be undefined.
            R = G = B = V;
        }
        else
        {
            if ( H == 360 ) H = 0;
            H /= 60;	// H is now in [0,6]
            int i = (int)( Math.floor( H ) );
            float f = H - i;
            float p = V * ( 1.0f - S );
            float q = V * ( 1.0f - ( S * f ) );
            float t = V * ( 1.0f - ( S * ( 1.0f - f ) ) );
            switch ( i )
            {
            case 0: R = V;	G = t;	B = p;	break;
            case 1: R = q;	G = V;	B = p;	break;
            case 2: R = p;	G = V;	B = t;	break;
            case 3: R = p;	G = q;	B = V;	break;
            case 4: R = t;	G = p;	B = V;	break;
            case 5: R = V;	G = p;	B = q;	break;
            }
        }

        return ( new CqColor( R, G, B ) );
    }
    
    /**
     * ＨＳＬ→ＲＧＢ変換
     * 
     * @return	このCqColorをRGB変換した、新しいCqColorオブジェクト
     */
    public CqColor	hsltorgb(){
    	
        float R, G, B, H = m_fRed * 360.0f, S = m_fGreen, L = m_fBlue;
        // HLS_TO_RGB from Foley, van Dam, Feiner, Hughes 2nd Ed. Pg 596

        float m2, m1;
        if ( L <= 0.5 ) m2 = L * ( 1.0f + S );
        else	m2 = L + S - ( L * S );
        m1 = 2 * L - m2;

        if ( S == 0 )
        {
            assert( m_fRed < 0 );
            R = G = B = L;
        }
        else
        {
            R = HSLValue( m1, m2, H + 120 );
            G = HSLValue( m1, m2, H );
            B = HSLValue( m1, m2, H - 120 );
        }

        return ( new CqColor( R, G, B ) );
    }
    
    /**
     * ＸＹＺ→ＲＧＢ変換。<br>
     * その実、このオブジェクトのコピーを渡すのみ。
     * 
     * @return	このCqColorをRGB変換した、新しいCqColorオブジェクト
     */
    public CqColor	XYZtorgb(){
        CqColor c = new CqColor( m_fRed, m_fGreen, m_fBlue );
        return c;
    }
    
    /**
     * xyY→ＲＧＢ変換。<br>
     * その実、このオブジェクトのコピーを渡すのみ。
     * 
     * @return	このCqColorをRGB変換した、新しいCqColorオブジェクト
     */
    public CqColor	xyYtorgb(){
        CqColor c = new CqColor( m_fRed, m_fGreen, m_fBlue );
        return c;
    }
    
    /**
     * YIQ→ＲＧＢ変換。<br>
     * その実、このオブジェクトのコピーを渡すのみ。
     * 
     * @return	このCqColorをRGB変換した、新しいCqColorオブジェクト
     */
    public CqColor	YIQtorgb(){
    	
    	CqColor c =  new CqColor( matRGBtoYIQ2.multiply( new CqVector3D( m_fRed, m_fGreen, m_fBlue ) ) );
    	
    	return ( c );
    }
	
    
    /**
     * 引数で指定された値からRGB値を算出する。<br>
     * ＨＳＬ→ＲＧＢ変換に用いる
     * 
     * @param n1	
     * @param n2	
     * @param hue	色相
     * @return	引数で指定された値をRGB値
     */
    private static float HSLValue( float n1, float n2, float hue )
    {
        float Value;

        if ( hue > 360 ) hue -= 360;
        else if ( hue < 0 ) hue += 360;

        if ( hue < 60 ) Value = n1 + ( n2 - n1 ) * hue / 60;
        else if ( hue < 180 ) Value = n2;
        else if ( hue < 240 ) Value = n1 + ( n2 - n1 ) * ( 240 - hue ) / 60;
        else	Value = n1;

        return ( Value );
    }
	
	//************************************************************************//
	//*** 演算子のオーバーロード
	//************************************************************************//
	
    /**
     * 
     * 配列参照演算子。
     * 0,1,2がそれぞれR,G,Bに相当する。それ以外の値の場合はBを返す。
     * 
     * @param i	0,1,2の整数
     * @return	相当するRGB
     */
    public float valueAt( int i )
    {
        if ( i==0 )			 return ( m_fRed );
        else if ( i == 1 )	 return ( m_fGreen );
        else				 return ( m_fBlue );
    }
    
    /**
     * 
     * 配列代入演算。
     * 0,1,2がそれぞれR,G,Bに相当する。それ以外の値の場合はBとなる。
     * 
     * @param i	0,1,2の整数
     * @param col	代入する値
     */
    public void setValueAt( int i, float col )
    {
    	if ( i==0 )			 m_fRed		= col;
    	else if ( i == 1 )	 m_fGreen	= col;
    	else				 m_fBlue	= col;
    }
    
    /**
	 * 代入演算子。<br>
	 * CqVector3Dの各要素をコピーする。
	 * 
	 * @param From	代入するCqVector3D
	 * @return	代入結果（this）
	 */
	public CqColor assignment( final float r , final float g ,final float b)
	{
		
		m_fRed = r;
		m_fGreen = g;
		m_fBlue = b;
		
		return this;
	}
	
	/**
	 * 代入演算子。<br>
	 * CqVector3Dの各要素をコピーする。
	 * 
	 * @param From	代入するCqVector3D
	 * @return	代入結果（this）
	 */
	public CqColor assignment( CqVector3D From )
	{
		
		m_fRed = From.x;
		m_fGreen = From.y;
		m_fBlue = From.z;
		
		return this;
	}

	/**
	 * 代入演算子。<br>
	 * CqColorの各要素をコピーする。
	 * 
	 * @param From	代入するCqColor
	 * @return	代入結果（this）
	 */
	public CqColor assignment( CqColor From )
	{
		
		m_fRed = From.m_fRed;
		m_fGreen = From.m_fGreen;
		m_fBlue = From.m_fBlue;
		
		return this;
	}
	
	/**
	 * 加算代入。<br>
	 * 各要素に対して加算代入を行う。
	 * 
	 * @param colFrom	加算するCqColor
	 * @return	計算結果（this）
	 */
	public CqColor assignAdd( final CqColor colFrom )
    {
        m_fRed += colFrom.m_fRed;	m_fGreen += colFrom.m_fGreen;	m_fBlue += colFrom.m_fBlue;
        return ( this );
    }
	
	/**
	 * 除算代入。<br>
	 * 各要素に対して除算代入を行う。
	 * 
	 * @param colFrom	除算するCqColor
	 * @return	計算結果（this）
	 */
	public CqColor assignSub( final CqColor colFrom )
    {
        m_fRed -= colFrom.m_fRed;	m_fGreen -= colFrom.m_fGreen;	m_fBlue -= colFrom.m_fBlue;
        return ( this );
    }
	
	/**
	 * 乗算代入。<br>
	 * 各要素に対して乗算代入を行う。
	 * 
	 * @param colFrom	乗算するCqColor
	 * @return	計算結果（this）
	 */
	public CqColor assignMul( final CqColor colFrom )
    {
        m_fRed *= colFrom.m_fRed;	m_fGreen *= colFrom.m_fGreen;	m_fBlue *= colFrom.m_fBlue;
        return ( this );
    }
	
	/**
	 * 除算代入。<br>
	 * 各要素に対して除算代入を行う。
	 * 
	 * @param colFrom	除算するCqColor
	 * @return	計算結果（this）
	 */
	public CqColor assignDiv( final CqColor colFrom )
    {
        m_fRed /= colFrom.m_fRed;	m_fGreen /= colFrom.m_fGreen;	m_fBlue /= colFrom.m_fBlue;
        return ( this );
    }
	
	
    /**
     * 加算代入。<br>
	 * 全要素に対して引数での加算代入を行う。
     * 
     * @param fScale	加算する値
     * @return	計算結果（this）
     */
    public CqColor assignAdd( float fScale )
    {
        m_fRed += fScale;	m_fGreen += fScale;	m_fBlue += fScale;
        return ( this );
    }
    
    /**
     * 除算代入。<br>
	 * 全要素に対して引数での除算代入を行う。
     * 
     * @param fScale	除算する値
     * @return	計算結果（this）
     */
    public CqColor assignSub( float fScale )
    {
        m_fRed -= fScale;	m_fGreen -= fScale;	m_fBlue -= fScale;
        return ( this );
    }
	
    /**
     * 乗算代入。<br>
	 * 全要素に対して引数での乗算代入を行う。
     * 
     * @param fScale	乗算する値
     * @return	計算結果（this）
     */
    public CqColor assignMul( float fScale )
    {
        m_fRed *= fScale;	m_fGreen *= fScale;	m_fBlue *= fScale;
        return ( this );
    }
	
    /**
     * 除算代入。<br>
	 * 全要素に対して引数での除算代入を行う。
     * 
     * @param fScale	除算する値
     * @return	計算結果（this）
     */
    public CqColor assignDiv( float fScale )
    {
        m_fRed /= fScale;	m_fGreen /= fScale;	m_fBlue /= fScale;
        return ( this );
    }
	
	/**
	 * 比較演算子。<br>
	 * すべての要素が互いに等しければtrueを返す。
	 * 
	 * @param colCmp	比較対象のCqColor
	 * @return	true：	全要素が等しい<br>
	 * 			false：	いずれかの要素が等しくない
	 */
	public boolean equals( final CqColor colCmp )
	{
		return ( ( m_fRed == colCmp.m_fRed ) && ( m_fGreen == colCmp.m_fGreen ) && ( m_fBlue == colCmp.m_fBlue ) );
	}
    
	/**
	 * 右比較演算子。<br>
	 * 全要素を比較し、全てが引数のそれより大きいか等しければtrueを返す。
	 * 
	 * @param colCmp	比較対象のCqColor
	 * @return	true：	全要素が大きいか等しい<br>
	 * 			false：	いずれかの要素が小さい
	 */
	public boolean ge( final CqColor colCmp )
	{
		return ( ( m_fRed >= colCmp.m_fRed ) && ( m_fGreen >= colCmp.m_fGreen ) && ( m_fBlue >= colCmp.m_fBlue ) );
	}
	
	/**
	 * 左比較演算子。<br>
	 * 全要素を比較し、全てが引数のそれより小さいか等しければtrueを返す。
	 * 
	 * @param colCmp	比較対象のCqColor
	 * @return	true：	全要素が小さいか等しい<br>
	 * 			false：	いずれかの要素が大きい
	 */
	public boolean le( final CqColor colCmp )
	{
		return ( ( m_fRed <= colCmp.m_fRed ) && ( m_fGreen <= colCmp.m_fGreen ) && ( m_fBlue <= colCmp.m_fBlue ) );
	}
	
	/**
	 * 右比較演算子。<br>
	 * 全要素を比較し、全てが引数のそれより大きければtrueを返す。
	 * 
	 * @param colCmp	比較対象のCqColor
	 * @return	true：	全要素が大きい<br>
	 * 			false：	いずれかの要素が小さいか等しい
	 */
	public boolean gt( final CqColor colCmp )
	{
		return ( ( m_fRed > colCmp.m_fRed ) && ( m_fGreen > colCmp.m_fGreen ) && ( m_fBlue > colCmp.m_fBlue ) );
	}
	
	/**
	 * 左比較演算子。<br>
	 * 全要素を比較し、全てが引数のそれより小さければtrueを返す。
	 * 
	 * @param colCmp	比較対象のCqColor
	 * @return	true：	全要素が小さい<br>
	 * 			false：	いずれかの要素が大きいか等しい
	 */
	public boolean lt( final CqColor colCmp )
	{
		return ( ( m_fRed < colCmp.m_fRed ) && ( m_fGreen < colCmp.m_fGreen ) && ( m_fBlue < colCmp.m_fBlue ) );
	}
	    
	/**
	 * 加算演算子。<br>
	 * 各要素に対して加算を行う。
	 * 
	 * @param f	加算する値
	 * @return	計算結果（!=this）
	 */
	public CqColor add( final float f )
	{
		CqColor r = new CqColor( this.m_fRed, this.m_fGreen, this.m_fBlue );
		return r.assignAdd(f);
	}
	
	/**
	 * 減算演算子。<br>
	 * 各要素に対して減算を行う。（CqColor-f）
	 * 
	 * @param f	減算する値
	 * @return	計算結果（!=this）
	 */
	public CqColor sub( final float f )
	{
		CqColor r = new CqColor( this.m_fRed, this.m_fGreen, this.m_fBlue );
		return r.assignSub(f);
	}
	
	/**
	 * 逆減算演算子。<br>
	 * 各要素に対して減算を行う。（f-CqColor）
	 * 
	 * @param f	減算する値
	 * @return	計算結果（!=this）
	 */
	public CqColor subInv( final float f )
	{
		CqColor r = new CqColor( f, f, f );
		return r.assignSub(this);
	}
    
	/**
	 * 乗算演算子。<br>
	 * 各要素に対して乗算を行う。
	 * 
	 * @param f	乗算する値
	 * @return	計算結果（!=this）
	 */
	public CqColor mul( final float f )
	{
		CqColor r = new CqColor( this.m_fRed, this.m_fGreen, this.m_fBlue );
		return r.assignMul(f);
	}
    
	/**
	 * 除算演算子。<br>
	 * 各要素に対して除算を行う。（CqColor/f）
	 * 
	 * @param f	除算する値
	 * @return	計算結果（!=this）
	 */
	public CqColor div( final float f )
	{
		CqColor r = new CqColor( this.m_fRed, this.m_fGreen, this.m_fBlue );
		return r.assignDiv(f);
	}
	
	/**
	 * 逆除算演算子。<br>
	 * 各要素に対して除算を行う。（f/CqColor）
	 * 
	 * @param f	除算する値
	 * @return	計算結果（!=this）
	 */
	public CqColor divInv( final float f )
	{
		CqColor r = new CqColor( f, f, f );
		return r.assignDiv(this);
	}
	
	/**
	 * 加算演算子。<br>
	 * 各要素に対して加算を行う。
	 * 
	 * @param b	加算するCqColor
	 * @return	計算結果（!=this）
	 */
	public CqColor add( final CqColor b )
	{
		CqColor r = new CqColor( this.m_fRed, this.m_fGreen, this.m_fBlue );
		return r.assignAdd(b);
	}
	
	
	/**
	 * 減算演算子。<br>
	 * 各要素に対して減算を行う。（CqColor-f）
	 * 
	 * @param b	減算するCqColor
	 * @return	計算結果（!=this）
	 */
	public CqColor sub( final CqColor b )
	{
		CqColor r = new CqColor( this.m_fRed, this.m_fGreen, this.m_fBlue );
		return r.assignSub(b);
	}
	
	/**
	 * 乗算演算子。<br>
	 * 各要素に対して乗算を行う。
	 * 
	 * @param b	乗算するCqColor
	 * @return	計算結果（!=this）
	 */
	public CqColor mul( final CqColor b )
	{
		CqColor r = new CqColor( this.m_fRed, this.m_fGreen, this.m_fBlue );
		return r.assignMul(b);
	}
	
	/**
	 * 除算演算子。<br>
	 * 各要素に対して除算を行う。（CqColor/f）
	 * 
	 * @param b	除算するCqColor
	 * @return	計算結果（!=this）
	 */
	public CqColor div( final CqColor b )
	{
		CqColor r = new CqColor( this.m_fRed, this.m_fGreen, this.m_fBlue );
		return r.assignDiv(b);
	}
	
	/**
	 * 符号反転。 <br>
	 * 全要素の符号を反転した値で新しいCqColorオブジェクトを作成して返す
	 * 
	 * @return	符号が逆の新しいCqColorオブジェクト
	 */
	public CqColor negate()
	{
		return  new CqColor( -this.m_fRed, -this.m_fGreen, -this.m_fBlue );
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "( red:"+m_fRed+" green:"+m_fGreen+" blue:"+m_fBlue+" )";
	}

}
