/**
  The HYBRIDSIM project (started 2010)
  For hierarchical symbolic analog IC analysis including sensitivity.

  Students involved in this project:
  	MA, Diming		(MS class 2008)
  	XU, Hui  			(MS class 2009)
  	LI, Xiaopeng 		(MS class 2009)

  Software Architect:
  	SHI, Guoyong		(Prof.)

  Shanghai Jiao Tong University (SJTU)
  School of Microelectronics
  (c) 2010; All Rights Reserved.
*/

/**
	GPDDnode.h
*/

#ifndef GPDDNODE_H	
#define GPDDNODE_H

#include <cstdio>
#include <vector>

#include "gpdd_struct.h"
#include "gpdd_global.h"
#include "BDDnode.h"
#include "Subgraph.h"
#include "complex.h"
//#include "option.h"


class sCoeffNode;
class ExpGPDDnode;

/**
	The class for the label of the GPDD node in GPDD reduce process.
*/
class GPDDnode_tag : public Comparable   
{                                       
public:

	/// The label of the current GPDD node.
		int label_top;
	
	/// The label of the GPDD node pointed by the short edge.
		int label_left;       
		
	/// The label of the GPDD node pointed by the open edge.
		int label_right;                      

	/**
		The constructor of GPDDnode_tag.
		@param tl: the label of the short child node.
		@param tr: the label of the open child node.
	*/
	GPDDnode_tag(int left = 0, int right = 0)
	{
		label_top = 0;
		label_left = left;
		label_right = right;
	};

	/**
		The destructor of GPDDnode_tag.
	*/
	~GPDDnode_tag(){};

	/**
	    The function to get the hash value.
		The hash value is generated by the labels of the short child node and open child node.
	*/
	virtual unsigned Hash(unsigned i = 0)
	{
		return ((label_left << 3) ^ (label_right << 7));
	}

	/**
	    The function to get the entry of the hash table.
	*/
	unsigned HashId()
	{
		return abs(label_left * TAG_PRIME1 + label_right) % TAG_PRIME2;
	}

	/**
	    The function to compare two GPDDnode_tags with the same hash value.
		@param p: the GPDDnode_tag with the same hash value with this GPDDnode_tag.
	*/
	virtual int Compare(Comparable *p);


	/**
		The function to set all the label in one GPDDnode_tag.
		@param tl: the label of the short child node.
		@param tr: the label of the open child node.
		@param ll: the label of current GPDD node.
	*/
	void SetTriple(int top, int left, int right)    // set the triple labels
	{
		label_top = top;
		label_left = left;
		label_right = right;
	};
};

/**
	The class for the vertices in the Graph-Pair Decision Diagram.
	Definition of binary decisions: 
		TRUE (SOLID) ARROW for the SYMBOL-IN operation;
		FALSE (DASHED) ARROW for the SYMBOL-OUT operation.
*/

class GPDDnode : public BDDnode
{
private:
	///  symbol index for each node.
	int	SymbolIndex;		// int symbIndex : 24;
		
	SymbNode *theSymbol;		// where you can get the symbol name

	///  the sign attached to the short edge.
		short Sign_IN		: 2;		// (+1) or (-1)

	///  the sign attached to the open edge.
		short Sign_OUT	: 2;		// (+1) or (-1)

	///  the pointer to the GPDD node issued by the short edge.
		GPDDnode *Vertex_IN;

	///  the pointer to the GPDD node issued by the open edge.
		GPDDnode *Vertex_OUT;

	///  the flag for identifying whether the node is visited or not.
///		bool visit_flag : 1;

	///  the order of the s-variable for approximate analysis.
		short order     : 10;

	///  the pointer to the left reduced graph.
		Subgraph *pGraph_L;

	///  the pointer to the right reduece graph.
		Subgraph *pGraph_R;

	///  the pointer to the next GPDD node in GPDD reducing.
		GPDDnode * pNext;

	///  the label tag for GPDD reducing.
		GPDDnode_tag pTag;

	///  the expression value of the node and its Subgraph.		       
		complex_t *val_ptr;			

	///  the sensitivity value of the node and its Subgraph.
		complex_t *sens_ptr;		// <<<<<< SENSITIVITY

	///  the number of the terms represented by the subgraph rooted by this GPDD node.
		double	NumTerms;	// double termN;

public:
//	double aT;		// (of no use; G. Shi)
	ExpGPDDnode* pExpandNode;

public:
	GPDDnode();

	/**
		The constructor with parameters for a GPDD node.
		@param SymbI: the index of the symbol represented this GPDD node.
		@param ss   : the sign attached to the short edge.
		@param so   : the sign attached to the open edge.
		@param LT   : the pointer to the left reduced graph.
		@param RT   : the pointer to the right reduced graph.
	*/
//	GPDDnode(int SymbI, int ss, int so, Subgraph * LT, Subgraph *RT);  // redefined
	GPDDnode(SymbNode *symbnode, int ss, int so, Subgraph * LT, Subgraph *RT);
	/**
		The destructor of a GPDD node.		
	*/
	~GPDDnode();

	/**
		Naming convenction: "xxxx_L" for the Left-graph and "xxxx_R" for the Right-graph
	*/

	inline int GetSign_L()			{return pGraph_L->GetSign();}
	inline int GetSign_R()			{return pGraph_R->GetSign();}

	inline int GetNumNodes_L()		{return pGraph_L->GetNumNodes();}
	inline int GetNumNodes_R()		{return pGraph_R->GetNumNodes();}

	inline int GetNumEdges_L()		{return pGraph_L->GetNumEdges();}
	inline int GetNumEdges_R()		{return pGraph_R->GetNumEdges();}
		
	inline EdgeInfo* GetGraph_L()	{return pGraph_L->GetSubgraph();}
	inline EdgeInfo* GetGraph_R() 	{return pGraph_R->GetSubgraph();}
	
	inline Subgraph* GetSubgraph_L()	{return pGraph_L;}
	inline Subgraph* GetSubgraph_R()	{return pGraph_R;}

	inline SymbNode* 	GetSymbol()			{ return theSymbol; }
	inline int 			GetSymbolIndex()		{ return SymbolIndex;}
	inline char* 		GetSymbolName()		{ return theSymbol->symbname; }
		
	/**
		Get the next GPDD node in GPDD reducing.
		@return a point to a GPDD node
	*/
	inline GPDDnode* GetNextNode()     {return pNext;}
	inline void SetNextNode(GPDDnode *pn)		{pNext = pn;}

	/**
		Get the label tag of a GPDD node.
		@return the label tag
	*/
		inline GPDDnode_tag * GetTag()	{return &pTag;}
		
	/**
		Get the number of the terms representing by the subgraph rooted by this GPDD node.
	*/	
	inline double GetNumTerms() {return NumTerms;};

	inline int GetSign_IN()			{return Sign_IN;}
	inline int GetSign_OUT()		{return Sign_OUT;}

	inline GPDDnode* GetVertex_IN()	{return Vertex_IN;}
	inline GPDDnode* GetVertex_OUT()		{return Vertex_OUT;}

	inline void SetSign_IN(int s)		{Sign_IN = s;}
	inline void SetSign_OUT(int o)		{Sign_OUT = o;}

	inline void SetVertex_IN(GPDDnode *ps)		{Vertex_IN = ps;}
	inline void SetVertex_OUT(GPDDnode *po)		{Vertex_OUT = po;}
		
    /**
		Get the highest order of the s-variable of the expression 
		represented by the subgraph rooted by this GPDD node.
	*/
	inline short GetOrder() {return order;}

	/**
		Set the highest order of the s-variable of the expression 
		@param o: the highest order of the s-variable of the expression.
	*/
		inline void SetOrder(short o) {order = o;}

		void  PrintGPDDnode(std::ostream &out);

	/**
	    The function to identify the type of this class
		@return GPDDNODE
	*/
		virtual int isa() {return GPDDNODE;}
	
	/**
	    The function to get the hash value.
	*/
		virtual unsigned Hash(unsigned i = 0);

	/**
	    The function to compare two GPDD nodes with the same hash value.
		@param p: the GPDD node with the same hash value with this GPDD node.
	*/
		virtual int Compare(Comparable *p);
	
	/**
	    The function to get the entry of the hash table.
	*/
	unsigned HashTreeID();

	inline complex_t GetValue() 		{return *val_ptr;}
	inline complex_t *GetValueP() 	{return val_ptr;}

	inline void SetValue(complex_t value)  { *val_ptr = value; }
	inline void SetValueP(complex_t *val_ptr0) { this->val_ptr = val_ptr0; }

	inline complex_t GetSens() 		{return *sens_ptr;}
	inline complex_t *GetSensP() 	{return sens_ptr;}

	/**
	    Set the complex_t sensitivity value of the expression represented by
		the subgraph rooted by this GPDD node.
		@param value: the complex_t value to be assigned.
	*/
		inline void SetSens(complex_t value)  { *sens_ptr = value; }

	/**
	    Set the point to the complex_t sensitivity value of the expression represented by
		the subgraph rooted by this GPDD node.
	*/
		inline void SetSensP(complex_t *sens_ptr0) { this->sens_ptr = sens_ptr0; }

///	inline bool GetVisitFlag() { return visit_flag; }
///	inline void SetVisitFlag(bool visited)  { visit_flag = visited; }

	/**
		Set the pointer to the left reduced graph.
	*/
		inline void SetLeftGraph(Subgraph *pl) {pGraph_L = pl;}

	/**
		Set the pointer to the right reduced graph.
	*/
		inline void SetRightGraph(Subgraph *pr) {pGraph_R = pr;}

	/**
		Set the number of the terms representing by the subgraph rooted by this GPDD node.
	*/
		inline void SetNumTerms(double d) {NumTerms = d;};
};


/**
	The class of the s-expanded GPDD nodes for representing 
	the coefficients of the s-variable.
*/
class sCoeffNode : public BDDnode//public Comparable
{
public:
	///	the point to the expanded GPDD node.
	ExpGPDDnode *pExpNode;

	sCoeffNode *Vertex_IN;
	sCoeffNode *Vertex_OUT;

	/// the pointer to the complex_t value of the expression.
	//complex_t *val_ptr;
	double 	Value;	// the coeff node is independent on 's', hence is real.

	/** 
		the label of the sCoeffNodes when reducing the decision diagram of
		the coefficents of the s-variable.
	 */
	int label;

	double NumTerms;

	/**
		the constructor of sCoeffNode.
		@param pNode:	the pointer to the expanded GPDD node.
		@param Vertex_IN:	the pointer to the sCoeffNode pointed by the short edge.
		@param Vertex_OUT:   the pointer to the sCoeffNode pointed by the open edge.
		@param val_ptr:	the pointer to the complex_t value of the expression.
	 */
	sCoeffNode(): BDDnode(),
		pExpNode(0), Vertex_IN(0), Vertex_OUT(0), NumTerms( -1)
	{}

	/**
		the destructor of the sCoeffNode.
	 */
	~sCoeffNode();

	virtual int isa() {return SCOEFFNODE;}

	/**
		The function to get the hash value.
	 */
	virtual unsigned Hash(unsigned i = 0);

	/**
		The function to compare two sCoeffNodes with the same hash value.
		@param p: the sCoeffNode with the same hash value with this sCoeffNode.
	 */
	virtual int Compare(Comparable *p);

	/**
		The function to get the entry of the hash table.
	 */
	unsigned HashGraphID();

	inline double 	GetValue() 	{ return Value; }
	inline void	SetValue(double val) 	{ Value = val; }
	
///	complex_t *GetValueP();
#if 0
	void print() const
	{
		std::printf("\n{%p, %p, %p, %p, %p, %6d, %.6E}", this, pNode, Vertex_IN, Vertex_OUT, val_ptr, label, NumTerms);
	}
#endif
} ;

/**
	The class for the nodes of expanded GPDD (ExpGPDDnode).
	All the lumped symbols are expanded into identical nodes in the 
	expanded graph-pair decision diagram.

	The ExpGPDDnode class also is used for performing s-coefficient calculation.
*/
class ExpGPDDnode : public BDDnode		//public Comparable
{
public:
	/// the pointer to the expanded GPDD node pointed by the short edge.
	ExpGPDDnode* Vertex_IN;

	/// the pointer to the expanded GPDD node pointed by the open edge.
	ExpGPDDnode* Vertex_OUT;

	/// the pointer to the corresponding GPDD node (may have lumped symbols).
	GPDDnode    * pGPDDnode;

	/// the index of the symbol.
	int		SymbolIndex;		// int symbIndex : 24;

	short 	Sign_IN		: 2;
	short 	Sign_OUT	: 2;

	/// the visit flag.
	bool 	visit_flag : 1;
					
	/// the number of the terms in the expanded tree pair decision diagram.
	double NumTerms;

	double	*SymbCountArray;

	// Two s-coeff lists are attached to each GPDDnode.
	std::vector<sCoeffNode*> 	*sCoeffList;
	std::vector<int>        		*sPowerList;

#if 0
	static int cnt;
	int id;
#endif

public:
	/**
		the default constructor for the nodes of the expanded tree pair decsion diagram.
	*/
	ExpGPDDnode();

	/**
		the constructor for the nodes of the expanded tree pair decsion diagram.
		@param pS: the pointer to the ExpGPDDnode node pointed by the short edge.
		@param pO: the pointer to the ExpGPDDnode node pointed by the open edge.
		@param pT: the pointer to the corresponding GPDD node.
		@param sn: the index of the symbol.
		@param ss: the sign attached to the short edge.
		@param so: the sign attached to the open edge.
	*/
	ExpGPDDnode(ExpGPDDnode* pS, ExpGPDDnode* pO, GPDDnode* pT, int sn, short ss, short so);

	/**
		the destructor for the nodes of the expanded tree pair decsion diagram.
	*/
	~ExpGPDDnode();

	/**
	    The function to identify the type of this class
		@return SEXPGPDDNODE
	*/
	virtual int isa() {return SEXPGPDDNODE;}

	/**
	    The function to get the hash value.
	*/
	virtual unsigned Hash(unsigned i = 0);

	/**
	    The function to compare two ExpGPDDnode with the same hash value.
		@param p: the ExpGPDDnode with the same hash value with this ExpGPDDnode.
	*/
	virtual int Compare(Comparable *p);

	/**
	    The function to get the entry of the hash table.
	*/
	unsigned HashTreeID();

	ExpGPDDnode* GetVertex_IN(){return Vertex_IN;}

	ExpGPDDnode* GetVertex_OUT(){return Vertex_OUT;}
};

#endif 

