// 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;

import static net.cellcomputing.himawari.library.EqFloatIndex.MPG_average_area;
import static net.cellcomputing.himawari.library.EqFloatIndex.MPG_max_area;
import static net.cellcomputing.himawari.library.EqFloatIndex.MPG_min_area;
import static net.cellcomputing.himawari.library.EqFloatIndex._Last_float;
import static net.cellcomputing.himawari.library.EqIntIndex.*;

import java.io.PrintStream;

import net.cellcomputing.himawari.util.HimawariLogger;
/**
 * 
 * 統計情報を含むクラス。
 *	 レンダリングセッションの前に、Initialise()を呼ばれなければなりません(また、
 *    それはコンストラクタと呼ばれます)。 
 *	 それぞれの個々のフレームの前では、InitialiseFrame()と呼ぶことによって、
 *    変数はリセットされなければなりません。
 *	 その後に、カウンタは、適切なIncXyz()-方法を呼ぶことによって、増加することができます。 
 *	 様々な回を測定するために、数個の組のStartXyzTimer()とStopXyZTimer()方法
 *    があります。
 *
 * 
 * 
 * @author NTT DATA Corporation
 */
public strictfp class CqStats {
		/**
		 * コンストラクタ<br>
		 * Initialiseを呼び出す
		 */
	    public CqStats()
	    {
	        Initialise();
	    }

	    /**
	     *  初期化メソッド。<br>
	     *  新しくレンダリングを開始する時に必ず呼び出される。
	     *  (即ち、全く新しいribファイルを読み込む時)
	     *  コンストラクタの中で呼び出され、initializeFrameメソッドをコールする
	     *
	     */
	    public void Initialise(){
	        m_Complete = 0.0f;
	        //	m_timeTotal = 0;
	        InitialiseFrame();
	    }
	    
	    /**
	     * 次のフレーム処理に移る前に全ての属性を初期化する。
	     * <br>
	     * ひとつの独立した情報を含む、全ての属性をリセットする。
	     * 新しいフレームをレンダリングする際、必ず呼び出される。
	     * (RiFrameBegi()内で)
	     * 
	     * 
	     */
	    public void InitialiseFrame(){
	        m_cTextureMemory 	= 0;
	        m_cTextureHits 		= new int[ 2 ][ 5 ];     ///memsetの代わりに初期化する
		    m_cTextureMisses 	= new int[ 5 ];     	///< Count of the hits encountered used by texturemap.cpp
	        m_timeTotalFrame.Reset();
	        m_timeSurface.Reset();
	        m_timeDisplacement.Reset();
	        m_timeImager.Reset();
	        m_timeAtmosphere.Reset();
	        m_timeSplits.Reset();
	        m_timeDicing.Reset();
	        m_timeRenderMPGs.Reset();
	        m_timeOcclusionCull.Reset();
	        m_timeDiceable.Reset();
	        m_timeTM.Reset();
	        m_timeMakeTexture.Reset();
	        m_timeMakeShadow.Reset();
	        m_timeMakeEnv.Reset();
	        m_timeFB.Reset();
	        m_timeDB.Reset();
	        m_timeParse.Reset();
	        m_timeProject.Reset();
	        m_timeCombine.Reset();
	        m_timeOthers.Reset();
	    }

	    /** 
	     * m_completeのgetter
	     */
	    public float	Complete()
	    {
	        return ( m_Complete );
	    }
	    
	    /** Set the percentage complete.
	     * m_Completeのsetter
	     * 
	     */
	    public void SetComplete( float complete )
	    {
	        m_Complete = complete;
	    }

		//! Increase an integer specified by an EqIntIndex value by one
	    /**
	     * EqIntIndexのフィールドに定義された値を指定し
	     * 指定された番号のm_intVars[index]をインクリメントする
	     * 
	     * @param index インクリメントする場所 EqIntIndexのフィールドが指定される
	     */
	    public static void IncI( final int index )
	    {
	        m_intVars[ index ]++;
	    }

		//! Decrease an integer specified by an EqIntIndex value by one
	    /**
 	     * EqIntIndexのフィールドに定義された値を指定し
	     * 指定された番号のm_intVars[index]をデクリメントする。
	     * 
	     * @param index デクリメントする場所 EqIntIndexのフィールドが指定される
	     */
	    public static void DecI( final int index )
	    {
	        m_intVars[ index ]--;
	    }

	    //! Set an integer specified by an EqIntIndex value to value
	    /**
	     * EqIntIndexのフィールドに定義された値を指定し
	     * 指定された番号のm_intVars[index]の値を指定された値valueにセットする
	     * 
	     * @param index 値をセットする場所 EqIntIndexのフィールドが指定される
	     * @param value セットする値
	     */
	    public static void setI( final int index, final int value )
	    {
	        m_intVars[ index ] = value;
	    }

	    //! Get an integer specified by an EqIntIndex value
	    /**
	     * m_intVarsの指定された場所の値を返却する
	     * 
	     * @param index 取得したい場所 EqIntIndexのフィールドが指定される
	     * @return 指定された場所の値
	     */
	    public static int getI( final int index )
	    {
	        return m_intVars[ index ];
	    }

	    //! Set a float specified by an EqfloatIndex value to value
	    /**
	     * m_floatVarsの指定された場所の値を
	     * 指定された値にセットする
	     * 
	     * @param index 指定する場所 EqFloatIndexのフィールドが指定される
	     * @param value セットする値
	     */
	    public static void setF(final int index, final float value )
	    {
	        m_floatVars[ index ] = value;
	    }

	    //! Get a float specified by an EqfloatIndex value
	    /**
	     * m_floatVarsの指定された場所の値を返却する
	     * 
	     * @param index 指定する場所 EqIntFloatのフィールドが指定される
	     * @return 指定された場所の値
	     */
	    public static float getF(final int index )
	    {
	        return m_floatVars[ index ];
	    }

	    /**
	     * log2(value)を求める。<br>
	     * JavaにはMath.log()が存在するので、底の変換公式を利用して
	     * log2を求めることとする 2005/08/04
	     * <br>
	     * 引数が0以下の場合はassertionが発生する。
	     * 
	     * @param value 入力値
	     * @return log2(value)が返る
	     * 
	     */
	    public static int log2( int value /* Must be 32-bit integer!! */ )
	    {
	    	// log2の計算においてAqsis
	    	assert( value >= 1 );
	    		
	    	//
	    	return (int)(StrictMath.log(value) / StrictMath.log(2));
	        // As described in http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
	        // This method should take roughly O(lg(N)) operations for a N-bit integer

	    }



	    /** Increase the texture memory used.
	     * texture memoryの使用数を指定された値でインクリメントする
	     * 
	     * @param n 増加数
	     */
	    public void	IncTextureMemory( int n)
	    {
	        m_cTextureMemory += n;
	    }
	    
	    /**
	     * IncTextureMemory(0)を呼び出す
	     */
	    public void	IncTextureMemory(){
	        IncTextureMemory(0);
	    }
	    /**
	     * 2次元配列のフィールドm_cTextureHitsに対して、
	     * 指定した場所をインクリメントする
	     * 
	     * @param primary 第1番目の配列番号
	     * @param which 第2番目の配列番号
	     */
	    public void IncTextureHits( int primary, int which )
	    {
	        m_cTextureHits[ primary ][ which ] ++;
	    }
	    
	    /**
	     * 配列のフィールド m_cTextureMissesに対して
	     * 指定した場所をインクリメントする
	     * 
	     * @param which 配列番号
	     */
	    public void IncTextureMisses( int which )
	    {
	        m_cTextureMisses[ which ] ++;
	    }

	    /** Get the texture memory used.
	     * m_cTextureMemoryのgetter
	     */
	    public int GetTextureMemory()
	    {
	        return m_cTextureMemory;
	    }


	    /** 
	     * Frameタイマをスタートさせる。
	     * 
	     * m_timeTotalFrameをリセットしてから
	     * スタートさせる。
	     * 
	     */
	    public void StartFrameTimer(){
	        m_timeTotalFrame.Reset();
	        if( !m_timeTotalFrame.isStarted() )
	            m_timeTotalFrame.Start();
	    }

	    /** 
	     * Frameタイマを止める。
	     * タイマをとめた後、総合時間を集計し、m_timeTotalに保持する。
	     * 
	     */
	    public void StopFrameTimer(){
	    	m_timeTotalFrame.Stop();
	    	//  +=をassignAddに変更 2005/08/04
	        m_timeTotal.assignAdd(m_timeTotalFrame);
	    }

	    /** Get the surface timer.
	     * SurfaceTimerのgetter
	    */
	    CqStatTimer SurfaceTimer()
	    {
	        return ( m_timeSurface );
	    }

	    /** Get the displacement timer.
	     * displacement timerのgetter
	    */
	    CqStatTimer DisplacementTimer()
	    {
	        return ( m_timeDisplacement );
	    }
	    /** Get the Imager timer.
	     * ImagerTimerの getter 
	     */
	    CqStatTimer ImagerTimer()
	    {
	        return ( m_timeImager );
	    }

	    /** Get the atmosphere timer.
	     * atmosphereTimerのgetter
	    */
	    CqStatTimer AtmosphereTimer()
	    {
	        return ( m_timeAtmosphere );
	    }

	    /** Get the splits timer.
	     * splitTimerのgetter
	    */
	    CqStatTimer SplitsTimer()
	    {
	        return ( m_timeSplits );
	    }

	    /** Get the dicing timer.
	     * DicingTimerのgetter
	    */
	    CqStatTimer DicingTimer()
	    {
	        return ( m_timeDicing );
	    }
	    /** Get the texturesampling timer.
	     * TextureMapTimerのgetter
	    */
	    CqStatTimer TextureMapTimer()
	    {
	        return ( m_timeTM );
	    }
	    /** Get the render MPGs timer.
	     * renderMPGSTimerのgetter
	    */
	    CqStatTimer RenderMPGsTimer()
	    {
	        return ( m_timeRenderMPGs );
	    }
	    /** Get the occlusion culling timer.
	     * OcclusionCullTimerのgetter
	    */
	    CqStatTimer OcclusionCullTimer()
	    {
	        return ( m_timeOcclusionCull );
	    }
	    /** Get the diceable timer.
	     * diceableTimerのgetter
	    */
	    CqStatTimer DiceableTimer()
	    {
	        return ( m_timeDiceable );
	    }
	    /** Get the MakeTextureV, MakeShadowV, ... timers
	     * MakeTextureTimerのgetter
	    */
	    CqStatTimer MakeTextureTimer()
	    {
	        return ( m_timeMakeTexture );
	    }
	    /**
	     * MakeShadowTimerのgetter
	     * 
	     */
	    CqStatTimer MakeShadowTimer()
	    {
	        return ( m_timeMakeShadow );
	    }
	    /**
	     * MakeEnvMPGSTimerのgetter
	     * 
	     */
	    CqStatTimer MakeEnvTimer()
	    {
	        return ( m_timeMakeEnv );
	    }
	    /**
	     * MakeFilterBucketのgetter
	     * 
	     */
	    CqStatTimer MakeFilterBucket()
	    {
	        return ( m_timeFB );
	    }
	    /**
	     * MakeDisplayBucketのgetter
	     */
	    CqStatTimer MakeDisplayBucket()
	    {
	        return ( m_timeDB );
	    }
	    /**
	     * MakeCombineのgetter
	     */
	    CqStatTimer MakeCombine()
	    {
	        return ( m_timeCombine );
	    }
	    /**
	     * MakeParseのgetter
	     */
	    CqStatTimer MakeParse()
	    {
	        return ( m_timeParse );
	    }
	    /**
	     * MakeProjectのgetter
	     */
	    CqStatTimer MakeProject()
	    {
	        return ( m_timeProject );
	    }
	    /**
	     * Othersのgetter
	     */
	    CqStatTimer Others()
	    {
	        return ( m_timeOthers );
	    }

	    //@}
	    
	    /**
	     * 指定されたレベルに応じたレンダリングの状態を出力する。
	     * 
	     * @param level  Verbosity level as set by Options "statistics" "endofframe"
	     */
	    public void PrintStats( int level ){
	    	/*
	    	 Minimum := 0
	    	 Normal  := 1
	    	 Verbose := 2
	    	 Max		:= 3
	    	 */
	    	HimawariLogger logger = HimawariLogger.getLogger();
	    	PrintStream MSG = System.out;
	    	
	    	
	    	float timeTotal = m_timeSurface.TimeTotal() +
	    	m_timeDisplacement.TimeTotal() +
	    	m_timeImager.TimeTotal() +
	    	m_timeAtmosphere.TimeTotal() +
	    	m_timeSplits.TimeTotal() +
	    	m_timeDicing.TimeTotal() +
	    	m_timeRenderMPGs.TimeTotal() +
	    	m_timeOcclusionCull.TimeTotal() +
	    	m_timeDiceable.TimeTotal() +
	    	m_timeMakeTexture.TimeTotal() +
	    	m_timeMakeShadow.TimeTotal() +
	    	m_timeMakeEnv.TimeTotal() +
	    	m_timeTM.TimeTotal() +
	    	m_timeFB.TimeTotal() +
	    	m_timeDB.TimeTotal() +
	    	m_timeParse.TimeTotal() +
	    	m_timeProject.TimeTotal() +
	    	m_timeCombine.TimeTotal() +
	    	m_timeOthers.TimeTotal();
	    	
	    	//! level >= 0
	    	logger.info( "Total render time: " + TimeToString( m_timeTotal.TimeTotal(), -1 ) + "\n" );
	    	logger.info( "Last frame: " + TimeToString( m_timeTotalFrame.TimeTotal(), -1 ) + "\n" );
	    	System.err.flush();
	    	
	    	
	    	if ( level >= 1 )
	    	{
	    		MSG.println();
	    		
	    		MSG.print("Parsing             : ");
	    		TimeToString( MSG, m_timeParse.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("Diceable check      : ");
	    		TimeToString( MSG, m_timeDiceable.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("Splitting           : ");
	    		TimeToString( MSG, m_timeSplits.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("Dicing              : ");
	    		TimeToString( MSG, m_timeDicing.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("Render MPGs         : ");
	    		TimeToString( MSG, m_timeRenderMPGs.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("Occlusion Culling   : ");
	    		TimeToString( MSG, m_timeOcclusionCull.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("Imager shading      : ");
	    		TimeToString( MSG, m_timeImager.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("Surface shading     : ");
	    		TimeToString( MSG, m_timeSurface.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("Displacement shading: ");
	    		TimeToString( MSG, m_timeDisplacement.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("Atmosphere shading  : ");
	    		TimeToString( MSG, m_timeAtmosphere.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("SampleTexture       : ");
	    		TimeToString( MSG, m_timeTM.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("Combine             : ");
	    		TimeToString( MSG, m_timeCombine.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("Project             : ");
	    		TimeToString( MSG, m_timeProject.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("FilterBucket        : ");
	    		TimeToString( MSG, m_timeFB.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("DisplayBucket       : ");
	    		TimeToString( MSG, m_timeDB.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("MakeTexture         : ");
	    		TimeToString( MSG, m_timeMakeTexture.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("MakeShadow          : ");
	    		TimeToString( MSG, m_timeMakeShadow.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("MakeCubeEnv         : ");
	    		TimeToString( MSG, m_timeMakeEnv.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		MSG.print("Others              : ");
	    		TimeToString( MSG, m_timeOthers.TimeTotal(), m_timeTotalFrame.TimeTotal() ).println();
	    		
	    		MSG.print("Total time measured : ");
	    		TimeToString( MSG, timeTotal, m_timeTotalFrame.TimeTotal() ).println();
	    		
	    		MSG.println();
	    		
	    		
	    		
	    	}
	    	//! Most important informations
	    	if ( level == 2 || level == 3 )
	    	{
	    		
	    		/*
	    		 -------------------------------------------------------------------
	    		 GPrim stats
	    		 */
	    		
	    		float _gpr_c_q = 100.0f * STATS_INT_GETI( GPR_culled ) / STATS_INT_GETI( GPR_created_total );
	    		float _gpr_u_q = 100.0f * STATS_INT_GETI( GPR_created_total ) / STATS_INT_GETI( GPR_allocated );
	    		
	    		MSG.print("Input geometry:\n\t" + STATS_INT_GETI( GPR_created ) + " primitives created\n\n"
	    				+ "\t"	+	STATS_INT_GETI( GPR_subdiv ) + " subdivision primitives\n\t"
	    				+			STATS_INT_GETI( GPR_nurbs )	 + " NURBS primitives\n\t"
	    				+			STATS_INT_GETI( GPR_poly )	 + " polygons\n\t"
	    				+			STATS_INT_GETI( GPR_crv )	 + " curves\n\t"
	    				+			STATS_INT_GETI( GPR_points ) + " points\n\t"
	    				+			STATS_INT_GETI( GPR_patch )	 + " patches\n\t"
	    				+			STATS_INT_GETI( GPR_quad )	 + " quadrics\n\t"
	    				+ "\n");
	    		
	    		MSG.print("GPrims:\n\t"
	    				+ STATS_INT_GETI( GPR_allocated ) +  " allocated\n\t"
	    				+ STATS_INT_GETI( GPR_created_total ) +  " used (" + _gpr_u_q + "%), " + STATS_INT_GETI( GPR_peak ) + " peak,\n\t"
	    				+ STATS_INT_GETI( GPR_culled ) + " culled (" + _gpr_c_q + "%)\n" + "\n");
	    		
	    		/*
	    		 GPrim stats - End
	    		 -------------------------------------------------------------------
	    		 */
	    		
	    		
	    		
	    		/*
	    		 -------------------------------------------------------------------
	    		 Geometry stats
	    		 */
	    		
	    		// Curves
	    		float _geo_crv_s_q = 100.0f * STATS_INT_GETI( GEO_crv_splits ) / STATS_INT_GETI( GPR_crv );
	    		float _geo_crv_s_c_q = 100.0f * STATS_INT_GETI( GEO_crv_crv ) / STATS_INT_GETI( GEO_crv_splits );
	    		float _geo_crv_s_p_q = 100.0f * STATS_INT_GETI( GEO_crv_patch ) / STATS_INT_GETI( GEO_crv_splits );
	    		
	    		// Procedural
	    		float _geo_prc_s_q = 100.0f * STATS_INT_GETI( GEO_prc_split ) / STATS_INT_GETI( GEO_prc_created );
	    		
	    		
	    		MSG.print("Geometry:\n\t"
	    				// Curves
	    				+ "Curves:\n"
	    				+					"\t\t" + STATS_INT_GETI( GPR_crv ) + " created\n\t"
	    				+					"\t" + STATS_INT_GETI( GEO_crv_splits ) + " split (" + _geo_crv_s_q + "%)\n\t\t\t"
	    				+							STATS_INT_GETI( GEO_crv_crv ) + " (" + _geo_crv_s_c_q + "%) into " + STATS_INT_GETI( GEO_crv_crv_created ) + " subcurves\n\t\t\t"
	    				+							STATS_INT_GETI( GEO_crv_patch ) + " (" + _geo_crv_s_p_q + "%) into " + STATS_INT_GETI( GEO_crv_patch_created ) + " patches\n\t"
	    				+ "Procedurals:\n"
	    				+					"\t\t" + STATS_INT_GETI( GEO_prc_created ) + " created\n\t"
	    				+					"\t" + STATS_INT_GETI( GEO_prc_split ) + " split (" + _geo_prc_s_q + "%)\n\t\t"
	    				+							STATS_INT_GETI( GEO_prc_created_dl ) + " dynamic load,\n\t\t"
	    				+							STATS_INT_GETI( GEO_prc_created_dra ) + " dynamic read archive,\n\t\t"
	    				+							STATS_INT_GETI( GEO_prc_created_prp ) + " run program\n\t\t"
	    				+ "\n");
	    		
	    		/*
	    		 GPrim stats - End
	    		 -------------------------------------------------------------------
	    		 */
	    		
	    		
	    		
	    		/*
	    		 -------------------------------------------------------------------
	    		 Grid stats
	    		 */
	    		
	    		int _grd_init =
	    			STATS_INT_GETI( GRD_size_4 ) +
	    			STATS_INT_GETI( GRD_size_8 ) +
	    			STATS_INT_GETI( GRD_size_16 ) +
	    			STATS_INT_GETI( GRD_size_32 ) +
	    			STATS_INT_GETI( GRD_size_64 ) +
	    			STATS_INT_GETI( GRD_size_128 ) +
	    			STATS_INT_GETI( GRD_size_256 ) +
	    			STATS_INT_GETI( GRD_size_g256 );
	    		
	    		int _grd_shade =
	    			STATS_INT_GETI( GRD_shd_size_4 ) +
	    			STATS_INT_GETI( GRD_shd_size_8 ) +
	    			STATS_INT_GETI( GRD_shd_size_16 ) +
	    			STATS_INT_GETI( GRD_shd_size_32 ) +
	    			STATS_INT_GETI( GRD_shd_size_64 ) +
	    			STATS_INT_GETI( GRD_shd_size_128 ) +
	    			STATS_INT_GETI( GRD_shd_size_256 ) +
	    			STATS_INT_GETI( GRD_shd_size_g256 );
	    		
	    		float	_grd_init_quote	=	100.0f *  _grd_init / STATS_INT_GETI( GRD_created );
	    		float	_grd_shade_quote=	100.0f *  _grd_shade / STATS_INT_GETI( GRD_created );
	    		float	_grd_cull_quote =	100.0f *  STATS_INT_GETI( GRD_culled ) / STATS_INT_GETI( GRD_created );
	    		
	    		float	_grd_4		=	100.0f * STATS_INT_GETI( GRD_size_4 ) / _grd_init;
	    		float	_grd_8		=	100.0f * STATS_INT_GETI( GRD_size_8 ) / _grd_init;
	    		float	_grd_16		=	100.0f * STATS_INT_GETI( GRD_size_16 ) / _grd_init;
	    		float	_grd_32		=	100.0f * STATS_INT_GETI( GRD_size_32 ) / _grd_init;
	    		float	_grd_64		=	100.0f * STATS_INT_GETI( GRD_size_64 ) / _grd_init;
	    		float	_grd_128	=	100.0f * STATS_INT_GETI( GRD_size_128 ) / _grd_init;
	    		float	_grd_256	=	100.0f * STATS_INT_GETI( GRD_size_256 ) / _grd_init;
	    		float	_grd_g256	=	100.0f * STATS_INT_GETI( GRD_size_g256 ) / _grd_init;
	    		
	    		float	_grd_shd_4		=	100.0f * STATS_INT_GETI( GRD_shd_size_4 ) / _grd_shade;
	    		float	_grd_shd_8		=	100.0f * STATS_INT_GETI( GRD_shd_size_8 ) / _grd_shade;
	    		float	_grd_shd_16		=	100.0f * STATS_INT_GETI( GRD_shd_size_16 ) / _grd_shade;
	    		float	_grd_shd_32		=	100.0f * STATS_INT_GETI( GRD_shd_size_32 ) / _grd_shade;
	    		float	_grd_shd_64		=	100.0f * STATS_INT_GETI( GRD_shd_size_64 ) / _grd_shade;
	    		float	_grd_shd_128	=	100.0f * STATS_INT_GETI( GRD_shd_size_128 ) / _grd_shade;
	    		float	_grd_shd_256	=	100.0f * STATS_INT_GETI( GRD_shd_size_256 ) / _grd_shade;
	    		float	_grd_shd_g256	=	100.0f * STATS_INT_GETI( GRD_shd_size_g256 ) / _grd_shade;
	    		
	    		
	    		
	    		
	    		MSG.print("Grids:\n\t"
	    				+ STATS_INT_GETI( GRD_created ) + " created, " + STATS_INT_GETI( GRD_peak ) + " peak,\n\t"
	    				+ _grd_init + " initialized (" + _grd_init_quote + "%),\n\t" + _grd_shade + " shaded (" + _grd_shade_quote + "%), " + STATS_INT_GETI( GRD_culled ) + " culled (" + _grd_cull_quote + "%)\n\n"
	    				+ "\tGrid count/size (diced grids):\n"
	    				+ "\t+------+------+------+------+------+------+------+------+\n"
	    				+ "\t|<=  4 |<=  8 |<= 16 |<= 32 |<= 64 |<=128 |<=256 | >256 |\n"
	    				+ "\t+------+------+------+------+------+------+------+------+\n\t|"
	    				
	    				+ String.format("%6d",STATS_INT_GETI( GRD_size_4 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_size_8 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_size_16 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_size_32 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_size_64 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_size_128 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_size_256 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_size_g256 )) + "|\n"
	    				+ "\t|" + String.format("%5.1f", _grd_4) + "%|"
	    				+ String.format("%5.1f", _grd_8) + "%|"
	    				+ String.format("%5.1f", _grd_16) + "%|"
	    				+ String.format("%5.1f", _grd_32) + "%|"
	    				+ String.format("%5.1f", _grd_64) + "%|"
	    				+ String.format("%5.1f", _grd_128) + "%|"
	    				+ String.format("%5.1f", _grd_256) + "%|"
	    				+ String.format("%5.1f", _grd_g256) + "%|\n"
	    				+ "\t+------+------+------+------+------+------+------+------+\n\n"
	    				+ "\tGrid count/size (shaded grids):\n"
	    				+ "\t+------+------+------+------+------+------+------+------+\n"
	    				+ "\t|<=  4 |<=  8 |<= 16 |<= 32 |<= 64 |<=128 |<=256 | >256 |\n"
	    				+ "\t+------+------+------+------+------+------+------+------+\n\t|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_shd_size_4 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_shd_size_8 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_shd_size_16 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_shd_size_32 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_shd_size_64 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_shd_size_128 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_shd_size_256 )) + "|"
	    				+ String.format("%6d",STATS_INT_GETI( GRD_shd_size_g256 )) + "|\n"
	    				+ "\t|" + String.format("%5.1f", _grd_shd_4) + "%|"
	    				+ String.format("%5.1f", _grd_shd_8) + "%|"
	    				+ String.format("%5.1f", _grd_shd_16) + "%|"
	    				+ String.format("%5.1f", _grd_shd_32) + "%|"
	    				+ String.format("%5.1f", _grd_shd_64) + "%|"
	    				+ String.format("%5.1f", _grd_shd_128) + "%|"
	    				+ String.format("%5.1f", _grd_shd_256) + "%|"
	    				+ String.format("%5.1f", _grd_shd_g256) + "%|\n"
	    				+ "\t+------+------+------+------+------+------+------+------+\n\n"
	    				+ "\n");
	    		
	    		/*
	    		 Grid stats - End
	    		 -------------------------------------------------------------------
	    		 */
	    		
	    		/* MPGS */
	    		
	    		
	    		/*
	    		 -------------------------------------------------------------------
	    		 MPG stats
	    		 */
	    		
	    		int _mpg_pushes_all = STATS_INT_GETI( MPG_pushed_forward ) + STATS_INT_GETI( MPG_pushed_down ) +
	    		STATS_INT_GETI( MPG_pushed_far_down );
	    		
	    		float _mpg_p_f =  100.0f * STATS_INT_GETI( MPG_pushed_forward ) / _mpg_pushes_all;
	    		float _mpg_p_d = 100.0f * STATS_INT_GETI( MPG_pushed_down ) / _mpg_pushes_all;
	    		float _mpg_p_fd = 100.0f * STATS_INT_GETI( MPG_pushed_far_down ) / _mpg_pushes_all;
	    		float _mpg_p_a = 100.0f * _mpg_pushes_all / STATS_INT_GETI( MPG_allocated );
	    		float _mpg_m_q = 100.0f * STATS_INT_GETI( MPG_missed ) /STATS_INT_GETI( MPG_allocated );
	    		
	    		// Sample hit quote
	    		int _mpg_hits =	STATS_INT_GETI ( MPG_sample_coverage0_125 ) +
	    		STATS_INT_GETI ( MPG_sample_coverage125_25 ) +
	    		STATS_INT_GETI ( MPG_sample_coverage25_375 ) +
	    		STATS_INT_GETI ( MPG_sample_coverage375_50 ) +
	    		STATS_INT_GETI ( MPG_sample_coverage50_625 ) +
	    		STATS_INT_GETI ( MPG_sample_coverage625_75 ) +
	    		STATS_INT_GETI ( MPG_sample_coverage75_875 ) +
	    		STATS_INT_GETI ( MPG_sample_coverage875_100 );
	    		
	    		float	_mpg_1		=	100.0f * STATS_INT_GETI( MPG_sample_coverage0_125 ) / _mpg_hits;
	    		float	_mpg_2		=	100.0f * STATS_INT_GETI( MPG_sample_coverage125_25 ) / _mpg_hits;
	    		float	_mpg_3		=	100.0f * STATS_INT_GETI( MPG_sample_coverage25_375 ) / _mpg_hits;
	    		float	_mpg_4		=	100.0f * STATS_INT_GETI( MPG_sample_coverage375_50 ) / _mpg_hits;
	    		float	_mpg_5		=	100.0f * STATS_INT_GETI( MPG_sample_coverage50_625 ) / _mpg_hits;
	    		float	_mpg_6		=	100.0f * STATS_INT_GETI( MPG_sample_coverage625_75 ) / _mpg_hits;
	    		float	_mpg_7		=	100.0f * STATS_INT_GETI( MPG_sample_coverage75_875 ) / _mpg_hits;
	    		float	_mpg_8		=	100.0f * STATS_INT_GETI( MPG_sample_coverage875_100 ) / _mpg_hits;
	    		
	    		MSG.print("Micropolygons:\n\t"
	    				+ STATS_INT_GETI( MPG_allocated ) + " created (" + STATS_INT_GETI( MPG_culled ) + " culled)\n"
	    				+ "\t" +STATS_INT_GETI( MPG_peak ) + " peak, " + STATS_INT_GETI( MPG_trimmed ) + " trimmed, ( " + STATS_INT_GETI( MPG_trimmedout ) + " completely ) " + STATS_INT_GETI( MPG_missed ) + " missed (" + _mpg_m_q + "%)\n\t"
	    				+ "\n\tMPG Area:\t" +STATS_INT_GETF( MPG_average_area ) / STATS_INT_GETI( MPG_allocated ) + " average \n\t\t\t"
	    				+ STATS_INT_GETF( MPG_min_area ) + " min\n\t\t\t"
	    				+ STATS_INT_GETF( MPG_max_area ) + " max\n\t"
	    				+ "\n\t% of sample hits:\n"
	    				+ "\t+------+------+------+------+------+------+------+------+\n"
	    				+ "\t|<=12,5|<=  25|<=37,5|<=  50|<=62,5|<= 75 |<=87,5|<= 100|\n"
	    				+ "\t+------+------+------+------+------+------+------+------+\n\t|"
	    				+ String.format("%5.1f", _mpg_1) + "%|"
	    				+ String.format("%5.1f", _mpg_2) + "%|"
	    				+ String.format("%5.1f", _mpg_3) + "%|"
	    				+ String.format("%5.1f", _mpg_4) + "%|"
	    				+ String.format("%5.1f", _mpg_5) + "%|"
	    				+ String.format("%5.1f", _mpg_6) + "%|"
	    				+ String.format("%5.1f", _mpg_7) + "%|"
	    				+ String.format("%5.1f", _mpg_8) + "%|\n"
	    				+ "\t+------+------+------+------+------+------+------+------+\n\n"
	    				+ "\n");
	    		
	    		/*
	    		 MPG Pushed
	    		 */
	    		MSG.print("\tPushes:\t" + _mpg_pushes_all + " MPGs pushed ("		+ _mpg_p_a			+ "%)\n\t\t"
	    				+ STATS_INT_GETI( MPG_pushed_forward )	+ " forward ("		+ _mpg_p_f	 + "%), "
	    				+ STATS_INT_GETI( MPG_pushed_down )		+ " down ("		+ _mpg_p_d	 + "%),\n\t\t"
	    				+ STATS_INT_GETI( MPG_pushed_far_down )	+ " far down ("	+ _mpg_p_fd + "%)\n"
	    				+ "\n");
	    		
	    		/*
	    		 MPG stats - End
	    		 -------------------------------------------------------------------
	    		 */
	    		
	    		
	    		
	    		/*
	    		 -------------------------------------------------------------------
	    		 Sampling
	    		 */
	    		
	    		float _spl_b_h = 100.0f * STATS_INT_GETI( SPL_bound_hits ) / STATS_INT_GETI( SPL_count );
	    		float _spl_h = 100.0f * STATS_INT_GETI( SPL_hits ) / STATS_INT_GETI( SPL_count );
	    		float _spl_m = 100.0f - _spl_b_h - _spl_h;
	    		
	    		int _spl_px = RiGlobal.QGetRenderContext().optCurrent().GetIntegerOptionIndex( "System", "PixelSamples" , 0 ).value;
	    		int _spl_py = RiGlobal.QGetRenderContext().optCurrent().GetIntegerOptionIndex( "System", "PixelSamples" , 1 ).value;
	    		
	    		MSG.print("Sampling:\n"
	    				+ "\tSamples per Pixel: " + _spl_px * _spl_py + " (" + _spl_px + " " + _spl_py + ")\n\t"
	    				+ STATS_INT_GETI( SPL_count ) + " samples" + "\n");
	    		MSG.print("\tHits: " + STATS_INT_GETI( SPL_hits ) + " (" + _spl_h + "%), "
	    				+ "bound hits: " + STATS_INT_GETI( SPL_bound_hits ) + " (" + _spl_b_h + "%),\n\tmisses: "
	    				+ (STATS_INT_GETI( SPL_count ) - STATS_INT_GETI( SPL_hits ) - STATS_INT_GETI( SPL_bound_hits )) + " (" + _spl_m + "%)\n"
	    				+ "\n");
	    		
	    		/*
	    		 Sampling - End
	    		 -------------------------------------------------------------------
	    		 */
	    		
	    		/*
	    		 Shading stats
	    		 -------------------------------------------------------------------
	    		 */
	    		int _shd_var_all = STATS_INT_GETI( SHD_var_array ) + STATS_INT_GETI( SHD_var_uniform ) + STATS_INT_GETI( SHD_var_varying );
	    		
	    		float _shd_var_a = 100.0f * STATS_INT_GETI( SHD_var_array ) / _shd_var_all;
	    		float _shd_var_u = 100.0f * STATS_INT_GETI( SHD_var_uniform ) / _shd_var_all;
	    		float _shd_var_v = 100.0f * STATS_INT_GETI( SHD_var_varying ) / _shd_var_all;
	    		
	    		float _shd_var_c_q = 100.0f * STATS_INT_GETI( SHD_var_created_total ) / _shd_var_all;
	    		
	    		
	    		MSG.print("Shading:\n\t"
	    				+					"Stack:\n\t\t"
	    				+					STATS_INT_GETI( SHD_stk_peak ) + " max stack depth\n\t\t"
	    				+					STATS_INT_GETI( SHD_stk_push ) + " push, " + STATS_INT_GETI( SHD_stk_pushv ) + " pushv\n\t\t"
	    				+					STATS_INT_GETI( SHD_stk_pop ) + " pop, " + STATS_INT_GETI( SHD_stk_release ) + " release\n\t\t"
	    				+					STATS_INT_GETI( SHD_stk_dup ) + " dup, " + STATS_INT_GETI( SHD_stk_drop ) + " drop\n\n\t"
	    				+					"Variables:\n\t\t"
	    				+							_shd_var_all + " allocated, " + STATS_INT_GETI( SHD_var_created_total )  + " created (" + _shd_var_c_q + "%), " + STATS_INT_GETI( SHD_var_peak ) + " peak\n\n\t\t"
	    				+					"Arrays:\n\t\t"
	    				+					"\t" + STATS_INT_GETI( SHD_var_array ) + " created (" + _shd_var_a + "%), " + STATS_INT_GETI( SHD_var_array_peak ) + " peak\n\t\t"
	    				+					"\t" + STATS_INT_GETI( SHD_var_array_init ) + " initialized\n\n\t\t"
	    				+					"Uniform:\n\t\t"
	    				+					"\t" + STATS_INT_GETI( SHD_var_uniform ) + " created (" + _shd_var_u + "%), " + STATS_INT_GETI( SHD_var_uniform_peak ) + " peak\n\t\t"
	    				+					"\t" + STATS_INT_GETI( SHD_var_uniform_init ) + " inits\n\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_uniform_float ) + " float\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_uniform_string ) + " string\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_uniform_point ) + " point\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_uniform_vector ) + " vector\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_uniform_normal ) + " normal\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_uniform_color ) + " color\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_uniform_matrix ) + " matrix\n\n\t\t"
	    				+					"Varying:\n\t\t"
	    				+					"\t" + STATS_INT_GETI( SHD_var_varying ) + " created (" + _shd_var_v + "%), " + STATS_INT_GETI( SHD_var_varying_peak ) + " peak\n\t\t"
	    				+					"\t" + STATS_INT_GETI( SHD_Var_varying_init ) + " inits\n\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_varying_float ) + " float\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_varying_string ) + " string\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_varying_point ) + " point\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_varying_vector ) + " vector\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_varying_normal ) + " normal\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_varying_color ) + " color\n\t\t"
	    				+					"\t\t" + STATS_INT_GETI( SHD_var_varying_matrix ) + " matrix\n\n\t"
	    				
	    				
	    				+	"Shadeop calls:\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_abs ) !=0 ) MSG.print(STATS_INT_GETI( SHD_so_abs ) + "\tabs\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_acos ) !=0) MSG.print( STATS_INT_GETI( SHD_so_acos ) + "\tacos\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ambient ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_ambient ) + "\tambient\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_area ) !=0 ) MSG.print( STATS_INT_GETI( SHD_so_area ) + "\tarea\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_asin ) !=0 ) MSG.print( STATS_INT_GETI( SHD_so_asin ) + "\tasin\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_atan ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_atan ) + "\tatan\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_atmosphere ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_atmosphere ) + "\tatmosphere\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_attribute ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_attribute ) + "\tattribute\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_bake ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_bake ) + "\tbake\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_bump ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_bump ) + "\tbump\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cDeriv ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_cDeriv ) + "\tcDeriv\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cDu )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cDu ) + "\tcDu\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cDv )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cDv ) + "\tcDv\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_calculatenormal ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_calculatenormal ) + "\tcalculatenormal\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ccellnoise1 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_ccellnoise1 ) + "\tccellnoise1\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ccellnoise2 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_ccellnoise2 ) + "\tccellnoise2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ccellnoise3 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_ccellnoise3 ) + "\tccellnoise3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ccellnoise4 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_ccellnoise4 ) + "\tccellnoise4\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ceil )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_ceil ) + "\tceil\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cenvironment2 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cenvironment2 ) + "\tcenvironment2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cenvironment3 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cenvironment3 ) + "\tcenvironment3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cclamp ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_cclamp ) + "\tcclamp\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_clamp )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_clamp ) + "\tclamp\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cmax )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cmax ) + "\tcmax\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cmin )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cmin ) + "\tcmin\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cmix )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cmix ) + "\tcmix\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cnoise1 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_cnoise1 ) + "\tcnoise1\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cnoise2 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_cnoise2 ) + "\tcnoise2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cnoise3 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cnoise3 ) + "\tcnoise3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cnoise4 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cnoise4 ) + "\tcnoise4\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_concat )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_concat ) + "\tconcat\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cos )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cos ) + "\tcos\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cpnoise1 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cpnoise1 ) + "\tcpnoise1\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cpnoise2 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cpnoise2 ) + "\tcpnoise2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cpnoise3 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cpnoise3 ) + "\tcpnoise3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cpnoise4 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cpnoise4 ) + "\tcpnoise4\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_crandom )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_crandom ) + "\tcrandom\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_cspline )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_cspline ) + "\tcspline\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_csplinea )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_csplinea ) + "\tcsplinea\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ctexture1 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_ctexture1 ) + "\tctexture1\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ctexture2 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_ctexture2 ) + "\tctexture2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ctexture3 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_ctexture3 ) + "\tctexture3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ctransform )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_ctransform ) + "\tctransform\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_degrees ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_degrees ) + "\tdegrees\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_depth )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_depth ) + "\tdepth\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_determinant )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_determinant ) + "\tdeterminant\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_diffuse ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_diffuse ) + "\tdiffuse\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_displacement )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_displacement ) + "\tdisplacement\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_distance )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_distance ) + "\tdistance\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_exp ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_exp ) + "\texp\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_external )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_external ) + "\texternal\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fDeriv ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fDeriv ) + "\tfDeriv\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fDu )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_fDu ) + "\tfDu\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fDv )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_fDv ) + "\tfDv\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_faceforward ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_faceforward ) + "\tfaceforward\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_faceforward2 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_faceforward2 ) + "\tfaceforward2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fcellnoise1 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fcellnoise1 ) + "\tfcellnoise1\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fcellnoise2 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_fcellnoise2 ) + "\tfcellnoise2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fcellnoise3 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_fcellnoise3 ) + "\tfcellnoise3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fcellnoise4 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_fcellnoise4 ) + "\tfcellnoise4\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fenvironment2 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_fenvironment2 ) + "\tfenvironment2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fenvironment3 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_fenvironment3 ) + "\tfenvironment3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_filterstep ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_filterstep ) + "\tfilterstep\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_filterstep2 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_filterstep2 ) + "\tfilterstep2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_floor ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_floor ) + "\tfloor\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fmix ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fmix ) + "\tfmix\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fnoise1 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fnoise1 ) + "\tfnoise1\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fnoise2 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fnoise2 ) + "\tfnoise2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fnoise3 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fnoise3 ) + "\tfnoise3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fnoise4 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fnoise4 ) + "\tfnoise4\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_format ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_format ) + "\tformat\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fpnoise1 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fpnoise1 ) + "\tfpnoise1\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fpnoise2 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fpnoise2 ) + "\tfpnoise2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fpnoise3 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_fpnoise3 ) + "\tfpnoise3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fpnoise4 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fpnoise4 ) + "\tfpnoise4\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_frandom ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_frandom ) + "\tfrandom\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fresnel ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fresnel ) + "\tfresnel\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fspline ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fspline ) + "\tfspline\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_fsplinea ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_fsplinea ) + "\tfsplinea\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ftexture1 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_ftexture1 ) + "\tftexture1\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ftexture2 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_ftexture2 ) + "\tftexture2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ftexture3 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_ftexture3 ) + "\tftexture3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_illuminance ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_illuminance ) + "\tilluminance\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_illuminate ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_illuminate ) + "\tilluminate\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_incident )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_incident ) + "\tincident\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_inversesqrt )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_inversesqrt ) + "\tinversesqrt\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_length )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_length ) + "\tlength\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_lightsource )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_lightsource ) + "\tlightsource\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_log ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_log ) + "\tlog\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_match )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_match ) + "\tmatch\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_max )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_max ) + "\tmax\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_min )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_min ) + "\tmin\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_mod )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_mod ) + "\tmod\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_mrotate )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_mrotate ) + "\tmrotate\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_mscale )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_mscale ) + "\tmscale\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_mtranslate )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_mtranslate ) + "\tmtranslate\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_normalize ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_normalize ) + "\tnormalize\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ntransform ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_ntransform ) + "\tntransform\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_occlusion )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_occlusion ) + "\tocclusion\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_opposite ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_opposite ) + "\topposite\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_option ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_option ) + "\toption\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pDeriv ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_pDeriv ) + "\tpDeriv\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pDu )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_pDu ) + "\tpDu\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pDv )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_pDv ) + "\tpDv\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pcellnoise1 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_pcellnoise1 ) + "\tpcellnoise1\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pcellnoise2 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_pcellnoise2 ) + "\tpcellnoise2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pcellnoise3 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_pcellnoise3 ) + "\tpcellnoise3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pcellnoise4 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_pcellnoise4 ) + "\tpcellnoise4\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pclamp ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_pclamp ) + "\tpclamp\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_phong )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_phong ) + "\tphong\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pmax ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_pmax ) + "\tpmax\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pmin )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_pmin ) + "\tpmin\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pmix )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_pmix ) + "\tpmix\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pnoise1 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_pnoise1 ) + "\tpnoise1\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pnoise2 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_pnoise2 ) + "\tpnoise2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pnoise3 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_pnoise3 ) + "\tpnoise3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pnoise4 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_pnoise4 ) + "\tpnoise4\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pow )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_pow ) + "\tpow\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ppnoise1 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_ppnoise1 ) + "\tppnoise1\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ppnoise2 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_ppnoise2 ) + "\tppnoise2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ppnoise3 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_ppnoise3 ) + "\tppnoise3\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ppnoise4 )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_ppnoise4 ) + "\tppnoise4\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_prandom )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_prandom ) + "\tprandom\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_printf ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_printf ) + "\tprintf\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_pspline )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_pspline ) + "\tpspline\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_psplinea )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_psplinea ) + "\tpsplinea\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_ptlined )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_ptlined ) + "\tptlined\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_radians )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_radians ) + "\tradians\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_reflect )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_reflect ) + "\treflect\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_refract )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_refract ) + "\trefract\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_rendererinfo )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_rendererinfo ) + "\trendererinfo\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_rotate )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_rotate ) + "\trotate\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_round )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_round ) + "\tround\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_scspline ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_scspline ) + "\tscspline\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_scsplinea )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_scsplinea ) + "\tscsplinea\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_setcomp )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_setcomp ) + "\tsetcomp\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_setmcomp )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_setmcomp ) + "\tsetmcomp\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_setxcomp )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_setxcomp ) + "\tsetxcomp\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_setycomp )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_setycomp ) + "\tsetycomp\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_setzcomp )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_setzcomp ) + "\tsetzcomp\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_sfspline )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_sfspline ) + "\tsfspline\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_sfsplinea ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_sfsplinea ) + "\tsfsplinea\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_shadername )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_shadername ) + "\tshadername\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_shadername2 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_shadername2 ) + "\tshadername2\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_shadow )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_shadow ) + "\tshadow\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_shadow1 ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_shadow1 ) + "\tshadow1\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_sign ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_sign ) + "\tsign\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_sin )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_sin ) + "\tsin\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_smoothstep ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_smoothstep ) + "\tsmoothstep\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_solar )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_solar ) + "\tsolar\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_specular ) !=0 ) MSG.print( STATS_INT_GETI( SHD_so_specular ) + "\tspecular\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_specularbrdf ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_specularbrdf ) + "\tspecularbrdf\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_spspline )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_spspline ) + "\tspspline\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_spsplinea )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_spsplinea ) + "\tspsplinea\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_sqrt )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_sqrt ) + "\tsqrt\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_step )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_step ) + "\tstep\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_surface )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_surface ) + "\tsurface\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_tan ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_tan ) + "\ttan\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_textureinfo ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_textureinfo ) + "\ttextureinfo\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_trace ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_trace ) + "\ttrace\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_transform )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_transform ) + "\ttransform\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_vmix )  !=0 ) MSG.print( STATS_INT_GETI( SHD_so_vmix ) + "\tvmix\n\t\t");
	    		if( STATS_INT_GETI( SHD_so_vtransform ) !=0  ) MSG.print( STATS_INT_GETI( SHD_so_vtransform ) + "\tvtransform\n\t\t");
	    		MSG.println();
	    		
	    		MSG.print("Attributes:\n\t");
	    		MSG.print("" + RiGlobal.Attribute_Stack.size() + " created\n" + "\n");
	    		
	    		// MSG << "Transforms:\n\t";
	    		// MSG << ( TqInt ) Transform_stack.size() << " created\n" << std::endl;
	    		
	    		MSG.print("Parameters:\n\t" + STATS_INT_GETI( PRM_created ) + " created, " + STATS_INT_GETI( PRM_peak ) + " peak\n" + "\n");
	    		
	    	}
	    	
	    	if ( level == 3 )
	    	{
	    		MSG.print("Textures            : " + m_cTextureMemory + " bytes used." + "\n");
	    		MSG.print("Textures hits       : " + "\n");
	    		for ( int i = 0; i < 5; i++ )
	    		{
	    			/* Only if we missed something */
	    			if ( m_cTextureHits[ 0 ][ i ] !=0  )
	    			{
	    				switch ( i )
	    				{
	    				case 0: MSG.print( "\t\t\tMipMap   P(");
	    				break;
	    				case 1: MSG.print( "\t\t\tCube Env.P(");
	    				break;
	    				case 2: MSG.print( "\t\t\tLatLong  P(");
	    				break;
	    				case 3: MSG.print( "\t\t\tShadow   P(");
	    				break;
	    				case 4: MSG.print( "\t\t\tTiles    P(");
	    				break;
	    				}
	    				MSG.print( 100.0f * ( ( float ) m_cTextureHits[ 0 ][ i ] / ( float ) ( m_cTextureHits[ 0 ][ i ] + m_cTextureMisses[ i ] ) ) + "%)" + " of " + m_cTextureMisses[ i ] + " tries" + "\n");
	    			}
	    			if ( m_cTextureHits[ 1 ][ i ] !=0  )
	    			{
	    				switch ( i )
	    				{
	    				case 0: MSG.print( "\t\t\tMipMap   S(");
	    				break;
	    				case 1: MSG.print( "\t\t\tCube Env.S(");
	    				break;
	    				case 2: MSG.print( "\t\t\tLatLong  S(");
	    				break;
	    				case 3: MSG.print( "\t\t\tShadow   S(");
	    				break;
	    				case 4: MSG.print( "\t\t\tTiles    S(");
	    				break;
	    				}
	    				MSG.print( 100.0f * ( ( float ) m_cTextureHits[ 1 ][ i ] / ( float ) ( m_cTextureHits[ 1 ][ i ] + m_cTextureMisses[ i ] ) ) + "%)" + "\n");
	    			}
	    			
	    		}
	    		MSG.println();
	    	}
	    }
	    /**
	     * 情報を表示する。 
	     *
	     */
	    public void PrintInfo(){
	    	HimawariLogger logger = HimawariLogger.getLogger();
	    	int psX, psY; //< Pixel Samples
	        int resX, resY;	//< Image resolution
	        int fX, fY;	//< Filter width
	        float gain, gamma; //< Exposure, gain
	        float pratio; //< PixelAspectRatio
	        int bX = 16, bY = 16; //< Bucket Size
	        int gs; //< Grid Size

	        psX = RiGlobal.QGetRenderContext().optCurrent().GetIntegerOptionIndex( "System", "PixelSamples" , 0 ).value;
	        psY = RiGlobal.QGetRenderContext().optCurrent().GetIntegerOptionIndex( "System", "PixelSamples" , 1 ).value;

	        resX = RiGlobal.QGetRenderContext().optCurrent().GetIntegerOptionIndex( "System", "Resolution" , 0 ).value;
	        resY = RiGlobal.QGetRenderContext().optCurrent().GetIntegerOptionIndex( "System", "Resolution" , 1 ).value;

	        fX = (int) RiGlobal.QGetRenderContext().optCurrent().GetFloatOptionIndex( "System", "FilterWidth" , 0 ).value;
	        fY = (int) RiGlobal.QGetRenderContext().optCurrent().GetFloatOptionIndex( "System", "FilterWidth" , 1 ).value;

	        gain = RiGlobal.QGetRenderContext().optCurrent().GetFloatOptionIndex( "System", "Exposure" , 0 ).value;
	        gamma = RiGlobal.QGetRenderContext().optCurrent().GetFloatOptionIndex( "System", "Exposure" , 1 ).value;

	        pratio = RiGlobal.QGetRenderContext().optCurrent().GetFloatOptionIndex( "System", "PixelAspectRatio" , 0 ).value;

	        int[] poptBucketSize = RiGlobal.QGetRenderContext().optCurrent().GetIntegerOption( "limits", "bucketsize" );
	        if ( poptBucketSize != null )
	        {
	            bX = poptBucketSize[ 0 ];
	            bY = poptBucketSize[ 1 ];
	        }

	       int[] poptGridSize = RiGlobal.QGetRenderContext().optCurrent().GetIntegerOption( "limits", "gridsize" );

	        if ( poptGridSize != null && poptGridSize.length > 0)
	            gs = poptGridSize[ 0 ];
	        else
	            gs = 256;

	        logger.info("Image settings:" + "\n");
	        logger.info("	Resolution: " + resX + " " + resY + "\n");
	        logger.info("	PixelAspectRatio: " + pratio + "\n");
	        logger.info("	Exposure:" + "\n");
	        logger.info("		Gain: " + gain + "\n");
	        logger.info("		Gamma: " + gamma + "\n");
	        logger.info("Shading:" + "\n");
	        logger.info("	Bucket size: [ " + bX + " " + bY + "]" + "\n");
	        logger.info("	Gridsize: " + gs + "\n");
	        logger.info("Anti-aliasing settings: " + "\n");
	        logger.info("	PixelSamples: " + psX + " " + psY + "\n");
	        logger.info("	FilterWidth: " + fX + " " + fY + "\n");
	        System.err.flush();
	    }
	    
	    /**
	     * 時間を文字にして出力する
	     * ticksがマイナスの場合は<invalid>と表示される
	     * 
	     * @param os 出力先ストリーム
	     * @param ticks 出力する時間(ミリ秒)
	     * @param tot 総時間(ミリ秒)
	     * @return 出力ストリーム(固定)
	     */
	    private PrintStream TimeToString( PrintStream os, float ticks, float tot ){
	        float t = (float)(ticks) / CLOCKS_PER_SEC;

	        // Is the time negative? Then there's a bug somewhere.
	        if ( t < 0.0 )
	        {
	            os.print("<invalid>");
	            return os;
	        }

	        // Round the time if it's more than 5sec
	        if ( t > 5.0 )
	        	t = Math.round(t);

	        int h = (int)( t / ( 60 * 60 ) );
	        int m = (int)( ( t / 60 ) - ( h * 60 ) );
	        float s = ( t ) - ( h * 60 * 60 ) - ( m * 60 );
	        if ( h > 0 )
	            os.print(String.format("%6d",h)+"hrs ");
	        if ( m > 0 )
	            os.print(String.format("%6d",m) + "mins ");
	        os.print(String.format("%6.1f",s) + "secs");
	        if( tot >= 0 )
	            os.print(" (" + String.format("%6.2f",(100.0f * ticks / tot)) +"%)");
	        return os;
	    }
	    private String TimeToString( float ticks, float tot ){
	    	
	    	String str = "";
	        float t = (float)(ticks) / CLOCKS_PER_SEC;

	        // Is the time negative? Then there's a bug somewhere.
	        if ( t < 0.0 )
	        {
	            str += "<invalid>";
	            return str;
	        }

	        // Round the time if it's more than 5sec
	        if ( t > 5.0 )
	        	t = Math.round(t);

	        int h = (int)( t / ( 60 * 60 ) );
	        int m = (int)( ( t / 60 ) - ( h * 60 ) );
	        float s = ( t ) - ( h * 60 * 60 ) - ( m * 60 );
	        if ( h > 0 )
	            str += String.format("%6d",h)+"hrs ";
	        if ( m > 0 )
	            str += String.format("%6d",m) + "mins ";
	        str += String.format("%6.1f",s) + "secs";
	        if( tot >= 0 )
	            str += " (" + String.format("%6.2f",(100.0f * ticks / tot)) +"%)";
	        return str;
	    }

	    //--マクロ変数 time.hに定義されている。
	    private static final int CLOCKS_PER_SEC = 1000;
		private float	m_Complete;						///< Current percentage complete.

	    private static float[]		m_floatVars 		= new float[ _Last_float ];///< Float variables
	    private static int[]		m_intVars 			= new int[ _Last_int ];	///< Int variables

	    private int m_cTextureMemory;     										///< Count of the memory used by texturemap.cpp
	    private int[][] m_cTextureHits 					= new int[ 2 ][ 5 ];   ///< Count of the hits encountered used by texturemap.cpp
	    private int[] m_cTextureMisses 					= new int[ 5 ];     	///< Count of the hits encountered used by texturemap.cpp

	    private CqStatTimer	m_timeTotal					= new CqStatTimer();	///< Total time spent on the entire animation.
	    private CqStatTimer m_timeTotalFrame			= new CqStatTimer();	///< Time spent on processing one individual frame.

	    private CqStatTimer m_timeSurface				= new CqStatTimer();	///< Time spent on surface shading.
	    private CqStatTimer m_timeImager				= new CqStatTimer();	///< Time spent on imager shading.
	    private CqStatTimer m_timeDisplacement			= new CqStatTimer();	///< Time spent on displacement shading.
	    private CqStatTimer m_timeAtmosphere			= new CqStatTimer();	///< Time spent on volume shading (atmosphere).
	    private CqStatTimer m_timeSplits				= new CqStatTimer();	///< Time spent on surface splitting.
	    private CqStatTimer m_timeDicing				= new CqStatTimer();	///< Time spent on surface dicing.
	    private CqStatTimer m_timeRenderMPGs			= new CqStatTimer();	///< Time spent on rendering MPGs.
	    private CqStatTimer m_timeOcclusionCull			= new CqStatTimer();	///< Time spent on occlusion culling.
	    private CqStatTimer m_timeDiceable				= new CqStatTimer();	///< Time spent on diceable checking.
	    private CqStatTimer m_timeTM					= new CqStatTimer();	///< Time spent on SampleMipMap checking.
	    private CqStatTimer m_timeMakeTexture			= new CqStatTimer();	///< Time spent on MakeTextureV call.
	    private CqStatTimer m_timeMakeShadow			= new CqStatTimer();	///< Time spent on MakeShadowV call.
	    private CqStatTimer m_timeMakeEnv				= new CqStatTimer();  	///< Time spent on MakeCubeEnvironmenV call.
	    private CqStatTimer m_timeFB					= new CqStatTimer();    ///< Time spent on Filter the Bucket call.
	    private CqStatTimer m_timeDB					= new CqStatTimer();    ///< Time spent on sending the Bucket information to the display.
	    private CqStatTimer m_timeCombine				= new CqStatTimer();    ///< Time spent on combining the bucket subpixels
	    private CqStatTimer m_timeParse					= new CqStatTimer();	///< Time spent on sending the parsing RIB file or Ri Calls
	    private CqStatTimer m_timeProject				= new CqStatTimer();	///< Time spent on sending the Project grids to raster space
	    private CqStatTimer m_timeOthers				= new CqStatTimer();	///< Time spent on init. the buckets

	    //---マクロ関数---//
	    /**
	     * 配列のフィールドm_intVarsに対して
	     * 指定された配列番号の値をインクリメントする
	     * 
	     * @param index インクリメントする配列番号
	     */
	    public static  void STATS_INC(int index ){
	    	gStats_IncI( index );
	    }
	    /**
	     * 配列のフィールドm_intVarsに対して
	     * 指定された配列番号の値をデクリメントする
	     * 
	     * @param index デクリメントする配列番号
	     */

	    public static void  STATS_DEC(int index ){
	    	gStats_DecI(index );
	    }
	    /**
	     * 配列のフィールドm_intVarsに対して
	     * 指定された配列番号の値を返却する
	     * 
	     * @param index 配列番号
	     * @return 指定された場所の値
	     */

	    public static int STATS_GETI(int index){
	    	return gStats_getI(index);
	    }
	    /**
	     * 配列のフィールドm_intVarsに対して
	     * 指定された配列番号の値を指定された値にセットする
	     * 
	     * @param index 配列番号
	     * @param value セットする値
	     */
	    
	    public static void STATS_SETI(int index,int value){
	    	gStats_setI(index,value);
	    }
	    /**
	     * 配列のフィールドm_floatVarsに対して
	     * 指定された配列番号の値を返却する
	     * 
	     * @param index 配列番号
	     * @return 指定された場所の値
	     */
	    public static float STATS_GETF(int index){
	    	return gStats_getF(index);
	    }
	    /**
	     * 配列のフィールドm_floatVarsに対して
	     * 指定された配列番号の値を指定された値にセットする
	     * 
	     * @param index 配列番号
	     * @param value セットする値
	     */

	    public static void STATS_SETF(int index,float value){
	    	gStats_setF(index,value);
	    }
	    
	    /**
	     * 配列のフィールドm_intVarsに対して
	     * 指定された配列番号の値を返却する
	     * 
	     * @param index 配列番号
	     * @return 指定された場所の値
	     */
	    public static int STATS_INT_GETI(int index){
	    	return getI(index);
	    }
	    /**
	     * 配列のフィールドm_floatVarsに対して
	     * 指定された配列番号の値を返却する
	     * 
	     * @param index 配列番号
	     * @return 指定された場所の値
	     */

	    public static float STATS_INT_GETF(int index){
	    	return getF(index);
	    }
	    //---global関数---//
	    public static float gStats_getF(int index){
	    	return( getF( index ) );
	    }
	    public static void gStats_setI(int index,int value){
	    	setI(index,value);
	    }
	    public static void gStats_IncI(int index){
	    	IncI( index );
	    }
	    public static void gStats_DecI(int index){
	    	DecI( index );
	    }
	    public static int gStats_getI(int index){
	    	return( getI( index ) );
	    }
	    public static void gStats_setF(int index,float value){
	    	setF(index,value);
	    }
	    

}
