/*************************************************************** 
	The GPDD Sensitivity Project (GPDD_Sens) 
 
	GPDD stands for "Graph-Pair Decision Diagram" 
 
Contributors: 
 
   CHEN, Weiwei		(MS 2007 graduate) 
   MENG, Xiaoxuan		(MS 2009 graduate) 
   ZENG, Mei			(MS 2010 graduate) 
   LI, Ji				(MS 2010 graduate) 
   MA, Diming			(MS 2011 graduate) 
 
   SHI, Guoyong 		(Prof)  shiguoyong@ic.sjtu.edu.cn 
 
   School of Microelectronics 
   Shanghai Jiao Tong University 
   (c) 2005 - 2010 
******************************************************************/ 

/**
	Analysis_AC.h
	
	For AC analysis based on GPDD.
	We define this class Analysis_AC in consideration of
	integration of this symbolic package in the future with a Spice package 
	which also has an AC analysis class.
*/

#ifndef		ANALYSIS_AC_H
#define		ANALYSIS_AC_H


#include	<iostream>
#include	<limits.h>

#include	"gpdd_global.h"
#include "GPDD.h"
#include "complex.h"


// --- Same parameters used by SPICE. -----
// AC step type
#define NO_TYPE		0
#define DECADE 		1		// multiply by 10
#define OCTAVE 		2		// multiply by 2
#define LINEAR 		3

// AC parameters
#define AC_DEC 		1
#define AC_OCT 		2
#define AC_LIN 		3
#define AC_START 	4
#define AC_STOP 		5
#define AC_STEPS 	6
//-----------------------------------------------

// AC Step Types.
//enum AC_STEP_TYPE  {NO_TYPE=0, DECADE, OCTAVE, LINEAR};


//struct E_value {
struct Complex_H {
	complex_t num;
	complex_t den;
};


using namespace std;

/**
	The class for performing numerical analysis onto the Tree Pair Decision Diagram (GPDD). 
*/
class Analysis_AC
{
public:

	Analysis_AC(GPDD *gpdd);
	~Analysis_AC();

	int  SetParameter( int index,  G_Value *value);

	inline GPDD *GetGPDD()  			{ return (pGPDD); }
	inline void SetGPDD(GPDD *gpdd) 	{ pGPDD = gpdd; }

	inline int 		GetNumFreqPoints()	{ return NumFreqPoints; }
	inline double* GetFreqVector()		{ return FreqVec; }
	
	inline double* GetMagVector()		{ return MagVec; }
	inline double* GetPhaseVector()		{ return PhaseVec; }

	const char*	GetACstepTypeName();

	int  InitAnalysis();

	int  RunACAnalysis();	// Run AC analysis for all frequency points

	void  DifferenceSensitivity(const string &paraname, double variation);	// in test

	complex_t 	EvaluateAtFreq(double freq);
	// Evaluate at a single freq point without s-expansion.

	complex_t	Evaluate_R(GPDDnode *P, double freq);
	// Recursive evaluation

	complex_t	EvaluateH(GPDDnode *P, double freq, HashTree *ht);
	// Evaluation using a hash table.

	Complex_H  	EvaluateFractionAtFreq(double freq);

	complex_t ExpandedEvaluationAtFreq(double freq);

	void  EvaluateCoefficients();
	void  EvaluateCoefficients_R(ExpGPDDnode *P);

	void  PrintCoefficients();
	void  PrintFreqResponse(char *to_file);
	void  PrintFreqResponse2(complex_t *respvec);
	
	void  PrintSensResponse(char *to_file);

	void  EvaluateResponseVector(complex_t *resp);
	

private:
	/// pointer to a GPDD.
	GPDD* pGPDD;

	// AC analysis parameters; using the same naming convection as in Spice.
	double ACstartFreq;
	double ACstopFreq;

	double ACfreqDelta; /* multiplier for decade/octave stepping, */
	                    	   /* increment for linear steps. */

	int  ACstepType;     	// [DEC|OCT|LIN] in the ".AC" command
	int  ACnumberSteps;	// [ND|NO|NP] in the ".AC" command

	double RelTol;		// relative numerical tolerance

	// The TF curve is obtained from the following two vectors:
	int			NumFreqPoints;		// Num of freq points.
	double		*FreqVec;		// A list of freq points.
	complex_t	*RespVec;		// A list of response points.
	double		*MagVec;		// The magnitude of the Resp vector
	double		*PhaseVec;		// The phase of the Resp vector
	
	complex_t	*SensVec;		// The sensitivity vector

	ofstream		ListFile;			// For listing frequency response.

	bool 	CurrTraversalMark;	// passed over from GPDD::TraversalMark
	
};

#endif

