00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef CNODE_HPP
00032 #define CNODE_HPP
00033
00034 #include <stdio.h>
00035 #include <math.h>
00036 #include <list>
00037 #include <set>
00038 #include "glue.h"
00039 #include "csymbol.h"
00040 #include "cdecl.h"
00041 #include "cvector.h"
00042 #include "cobstack.h"
00043 #include "cattr.h"
00044
00045 class CGenvar;
00046 class CReal;
00047 class CParam;
00048 class CFref;
00049 class CReg;
00050 class CNet;
00051 class CPort;
00052 class CPortDir;
00053 class CInstance;
00054 class CFunction;
00055 class CModule;
00056 class CGate;
00057 class CEvent;
00058 class CAttr;
00059 class CBlock;
00060 class CSpecify;
00061 class CNode;
00062 typedef CBlock CScope;
00063 inline char* d2s( double d, CObstack* stack );
00064
00068 enum Edge_t {
00069 eEDGE01 = 0x1,
00070 eEDGE10 = 0x2,
00071 eEDGE0x = 0x4,
00072 eEDGEx1 = 0x8,
00073 eEDGE1x = 0x10,
00074 eEDGEx0 = 0x20,
00075 };
00076
00080 enum DelayMode_t {
00081 eMIN_DELAY,
00082 eTYP_DELAY,
00083 eMAX_DELAY
00084 };
00085
00089 enum Strength_t {
00090 eUNDEFINED = 0,
00091 eSUPPLY,
00092 eSTRONG,
00093 ePULL,
00094 eLARGE,
00095 eWEAK,
00096 eMEDIUM,
00097 eSMALL,
00098 eHIGHZ,
00099 };
00100
00104 struct StrengthPair_t {
00105 Strength_t s0;
00106 Strength_t s1;
00107 };
00108
00109 #define DEFINE_ENUM
00110 #include "cnode_def.h"
00111 #undef DEFINE_ENUM
00112
00113
00120 template<class T>
00121 class CNode_sp {
00122 T* ptr;
00123 public:
00124 CNode_sp( void** np ) { ptr = (T*)np; }
00125 T operator=( T n ) { *ptr = n; return n; }
00126 T operator->() { return *ptr; }
00127 operator T() { return *ptr; }
00128 int operator==( T v ) { return *ptr == v; }
00129 int operator!=( T v ) { return *ptr != v; }
00130 int operator==( CNode_sp<T> p ) { return *ptr == *p.ptr; }
00131 int operator!=( CNode_sp<T> p ) { return *ptr != *p.ptr; }
00132 };
00133
00138 struct CNode_pr {
00139 CNode* head;
00140 CNode* tail;
00141 public:
00142 CNode* operator=( CNode* n ) { head = n; tail = n; return n; }
00143 CNode* operator->() { return head; }
00144 operator CNode*() { return head; }
00145 int operator==( CNode* v ) { return head == v; }
00146 int operator!=( CNode* v ) { return head != v; }
00147 int operator==( CNode_pr p ) { return head == p.head; }
00148 int operator!=( CNode_pr p ) { return head != p.head; }
00149 friend CNode_pr cLINK( CNode_pr pr1, CNode* n2 );
00150 };
00151
00172 class CNode : public CObject
00173 {
00174 private:
00175 static list<CObstack*> stackList;
00176 static CObstack evalHeap;
00177 static INT32 evalCount;
00178 static CObstack* stack;
00179 static map<CNode*,int> labelCache;
00180 static int labelCacheEnabled;
00181 NodeOp_t op;
00182 void* left;
00183 void* right;
00184 Coord_t loc;
00185 Coord_t *locp;
00186 CNode* attributes;
00187
00188
00189
00190
00191 NodeType_t type;
00192 INT32 width;
00193 int fixedWidth;
00194 private:
00195 int LabelBits( int supressErrorMessages = FALSE );
00196 CNode* FixBits( INT32 newWidth, NodeType_t newType );
00197 void _EvalVector( CVector& v );
00198 double _EvalReal( void );
00199 void FixedWidth( int v ) { fixedWidth = v; }
00200 int FixedWidth() { return fixedWidth; }
00201 int ConditionalWiden();
00202 int WidthFixed();
00203 unsigned NodeMask();
00204 CNode* GetNLeft( void ) { return (CNode*)left; }
00205 CNode* GetNRight( void ) { return (CNode*)right; }
00206 static void _LabelBits( CNode* n, void* arg );
00207 public:
00212 static CObstack* CurrentHeap() { return stack; }
00222 static void UseEvalStack( void ) {
00223 stackList.push_front( stack );
00224 evalCount++;
00225 stack = &evalHeap;
00226 }
00231 static void SetBuildStack( CObstack* aStack ) {
00232 MASSERT( evalCount == 0 );
00233 stackList.push_front( stack );
00234 stack = aStack;
00235 }
00239 static void ResetBuildStack( void ) {
00240 if( stack == &evalHeap ) {
00241 evalCount--;
00242 if( evalCount == 0 ) {
00243 evalHeap.Free( NULL );
00244 }
00245 }
00246 if( stackList.empty() ) {
00247 stack = NULL;
00248 } else {
00249 stack = *stackList.begin();
00250 stackList.pop_front();
00251 }
00252 }
00262 static void EnableLabelCache()
00263 {
00264 labelCacheEnabled = 1;
00265 }
00270 static void DisableAndClearLabelCache()
00271 {
00272 labelCacheEnabled = 0;
00273 labelCache.erase( labelCache.begin(), labelCache.end() );
00274 }
00282 CNode( Coord_t* aLoc, NodeOp_t aOp );
00287 Coord_t* GetCoord() { return locp; }
00292 NodeOp_t GetOp() { return op; }
00299 void SetOp( NodeOp_t aOp ) {
00300 int oldCount = ArgCount();
00301 op = aOp;
00302 MASSERT( oldCount == ArgCount() );
00303 }
00309 unsigned Hash();
00315 template<class T> CNode_sp<T> Arg( int index );
00320 int ArgCount( void );
00326 CNode* Clone( void );
00331 int Precedence();
00338 void PostVisit1( void (*callback)(CNode*,void*), void* data );
00347 CNode* PostSubVisit1( CNode* (*callback)(CNode*,void*),
00348 void* data );
00356 void PreVisit1( int (*callback)(CNode*,void*), void* data );
00365 CNode* Simplify( INT32 newWidth, NodeType_t newType );
00375 int IsNonX( int integerIsNonX = 0, char* exclude = NULL );
00381 int IsConstant();
00391 int IsEvaluateable();
00397 int IsVolatile( void );
00402 INT32 EvalINT32();
00409 void EvalVector( CVector& v );
00418 void EvalVector( CVector& v, INT32 newWidth, NodeType_t newType );
00424 double EvalReal( void );
00429 void Dump( FILE* f );
00435 int IsWidthConstant( void );
00441 int IsWidthVolatile( void );
00451 int IsWidthEvaluateable( void );
00456 CNode* GetWidthExp( void );
00462 INT32 GetWidth( void ) { LabelBits(TRUE); return width; }
00467 int IsScalar( void ) { LabelBits(TRUE); return width==1; }
00472 int IsVector( void ) { LabelBits(TRUE); return width>1; }
00477 int IsReal( void ) { LabelBits(TRUE); return type==eR; }
00482 CNode* GetAttributes() { return attributes; }
00487 void SetAttributes( CNode* attr ) { attributes = attr; }
00495 int HasAttribute( const char* name, CNode* n=NULL, int init = 1 );
00503 CAttr* GetAttribute( const char* name, CNode* n=NULL, int init = 1 );
00508 NodeType_t GetNodeType( void ) { LabelBits(TRUE); return type; }
00509 };
00510
00511
00512
00513
00514
00515
00516
00517 template<class T> CNode_sp<T> CNode::Arg(int index)
00518 {
00519 switch( ArgCount() ) {
00520 case 1:
00521 switch( index ) {
00522 case 0:
00523 return CNode_sp<T>(&left);
00524 default:
00525 MASSERT( FALSE );
00526 return NULL;
00527 }
00528 case 2:
00529 switch( index ) {
00530 case 0:
00531 return CNode_sp<T>(&left);
00532 case 1:
00533 return CNode_sp<T>(&right);
00534 default:
00535 MASSERT( FALSE );
00536 return NULL;
00537 }
00538 case 3:
00539 switch( index ) {
00540 case 0:
00541 return CNode_sp<T>(&GetNLeft()->left);
00542 case 1:
00543 return CNode_sp<T>(&GetNLeft()->right);
00544 case 2:
00545 return CNode_sp<T>(&right);
00546 default:
00547 MASSERT( FALSE );
00548 return NULL;
00549 }
00550 case 4:
00551 switch( index ) {
00552 case 0:
00553 return CNode_sp<T>(&GetNLeft()->left);
00554 case 1:
00555 return CNode_sp<T>(&GetNLeft()->right);
00556 case 2:
00557 return CNode_sp<T>(&GetNRight()->left);
00558 case 3:
00559 return CNode_sp<T>(&GetNRight()->right);
00560 default:
00561 MASSERT( FALSE );
00562 return NULL;
00563 }
00564 case 5:
00565 switch( index ) {
00566 case 0:
00567 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00568 case 1:
00569 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00570 case 2:
00571 return CNode_sp<T>(&GetNLeft()->right);
00572 case 3:
00573 return CNode_sp<T>(&GetNRight()->left);
00574 case 4:
00575 return CNode_sp<T>(&GetNRight()->right);
00576 default:
00577 MASSERT( FALSE );
00578 return NULL;
00579 }
00580 case 6:
00581 switch( index ) {
00582 case 0:
00583 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00584 case 1:
00585 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00586 case 2:
00587 return CNode_sp<T>(&GetNLeft()->GetNRight()->left);
00588 case 3:
00589 return CNode_sp<T>(&GetNLeft()->GetNRight()->right);
00590 case 4:
00591 return CNode_sp<T>(&GetNRight()->left);
00592 case 5:
00593 return CNode_sp<T>(&GetNRight()->right);
00594 default:
00595 MASSERT( FALSE );
00596 return NULL;
00597 }
00598 case 7:
00599 switch( index ) {
00600 case 0:
00601 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00602 case 1:
00603 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00604 case 2:
00605 return CNode_sp<T>(&GetNLeft()->GetNRight()->left);
00606 case 3:
00607 return CNode_sp<T>(&GetNLeft()->GetNRight()->right);
00608 case 4:
00609 return CNode_sp<T>(&GetNRight()->GetNLeft()->left);
00610 case 5:
00611 return CNode_sp<T>(&GetNRight()->GetNLeft()->right);
00612 case 6:
00613 return CNode_sp<T>(&GetNRight()->right);
00614 default:
00615 MASSERT( FALSE );
00616 return NULL;
00617 }
00618 case 8:
00619 switch( index ) {
00620 case 0:
00621 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00622 case 1:
00623 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00624 case 2:
00625 return CNode_sp<T>(&GetNLeft()->GetNRight()->left);
00626 case 3:
00627 return CNode_sp<T>(&GetNLeft()->GetNRight()->right);
00628 case 4:
00629 return CNode_sp<T>(&GetNRight()->GetNLeft()->left);
00630 case 5:
00631 return CNode_sp<T>(&GetNRight()->GetNLeft()->right);
00632 case 6:
00633 return CNode_sp<T>(&GetNRight()->GetNRight()->left);
00634 case 7:
00635 return CNode_sp<T>(&GetNRight()->GetNRight()->right);
00636 default:
00637 MASSERT( FALSE );
00638 return NULL;
00639 }
00640
00641 default:
00642 MASSERT( FALSE );
00643 }
00644 }
00645 int Equivalent( CNode* a, CNode* b );
00646
00647
00648
00649
00650 inline void Add( double* r, double* a, double* b )
00651 {
00652 *r = *a + *b;
00653 }
00654
00655 inline void Sub( double* r, double* a, double* b )
00656 {
00657 *r = *a - *b;
00658 }
00659
00660 inline void Mul( double* r, double* a, double* b )
00661 {
00662 *r = *a * *b;
00663 }
00664
00665 inline void Div( double* r, double* a, double* b )
00666 {
00667 *r = *a / *b;
00668 }
00669
00670 inline void Neg( double* r, double* a )
00671 {
00672 *r = - *a;
00673 }
00674
00675 inline void Pow( double* r, double* a, double* b )
00676 {
00677 *r = pow(*a,*b);
00678 }
00679
00680
00681
00682
00683
00684 #define ILLEGAL_OP2(op) \
00685 inline void op( double*, double*, double* )\
00686 { fatal( NULL, #op " is illegal for reals" ); }
00687
00688 #define ILLEGAL_OP1(op) \
00689 inline void op( double*, double* )\
00690 { fatal( NULL, #op " is illegal for reals" ); }
00691
00692 ILLEGAL_OP2(Rsh);
00693 ILLEGAL_OP2(Lsh);
00694
00695 ILLEGAL_OP2(Rep);
00696 ILLEGAL_OP2(Mod);
00697 ILLEGAL_OP2(And);
00698 ILLEGAL_OP2(Xor);
00699 ILLEGAL_OP2(Xnor);
00700 ILLEGAL_OP2(Or);
00701 ILLEGAL_OP2(Lor);
00702 ILLEGAL_OP2(Land);
00703 ILLEGAL_OP1(Com);
00704 ILLEGAL_OP1(Rand);
00705 ILLEGAL_OP1(Rnand);
00706 ILLEGAL_OP1(Ror);
00707 ILLEGAL_OP1(Rnor);
00708 ILLEGAL_OP1(Rxor);
00709 ILLEGAL_OP1(Rxnor);
00710
00711 #define DEFINE_CONSTRUCTOR
00712 #include "cnode_def.h"
00713 #undef DEFINE_CONSTRUCTOR
00714
00715
00716
00717
00718
00725 inline CNode* cVECTOR( CVector& vec )
00726 {
00727 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), vec.GetWidth() );
00728 CNode* n;
00729 *v = vec;
00730 v->SetPreferredBase( vec.GetPreferredBase() );
00731 n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00732 n->Arg<CVector*>(0) = v;
00733 return n;
00734 }
00735
00742 inline CNode* cSTRING( const char* s )
00743 {
00744 int len = strlen( s );
00745 if( !len ) {
00746 len = 1;
00747 }
00748 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), len*8 );
00749 v->LoadString( s );
00750 CNode* n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00751 n->Arg<CVector*>(0) = v;
00752 return n;
00753 }
00754
00761 inline CNode* cINT32( INT32 i )
00762 {
00763 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), 32 );
00764 CNode* n;
00765 *v = i;
00766 v->Sized(FALSE);
00767 v->Signed(TRUE);
00768 v->Based(FALSE);
00769 n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00770 n->Arg<CVector*>(0) = v;
00771 return n;
00772 }
00773
00780 inline CNode* cREAL( double number )
00781 {
00782 CNode* node = new(CNode::CurrentHeap()) CNode( NULL, eRCONSTANT );
00783 node->Arg<char*>(0) = d2s(number,CNode::CurrentHeap());
00784 return node;
00785 }
00786
00794 inline CNode* cELINK( CNode* n1, CNode* n2 )
00795 {
00796 if( n1 == NULL ) {
00797 return n2;
00798 } else if( n2 == NULL ) {
00799 return n1;
00800 }
00801 return cELIST( n1, n2 );
00802 }
00803
00811 inline CNode* cABS( CNode* a )
00812 {
00813 CNode* a1 = a->Clone();
00814 CNode* a2 = a->Clone();
00815 CNode* c = cGE(a,cINT32(0));
00816 return cHOOK( c, a1, cNEG( a2) );
00817 }
00818
00827 inline CNode* cABSDIFF( CNode* a, CNode* b )
00828 {
00829 return cABS( cSUB( a, b ) );
00830 }
00831
00840 inline CNode* cLINK( CNode* n1, CNode* n2 )
00841 {
00842 if( n1 == NULL ) {
00843 return n2;
00844 } else if( n2 == NULL ) {
00845 return n1;
00846 }
00847 return cLIST( n1, n2 );
00848 }
00849
00858 inline CNode* cMAX( CNode* n1, CNode* n2 )
00859 {
00860 CNode* cond = cLT(n2->Clone(),n1->Clone());
00861 return cHOOK(cond,n1,n2);
00862 }
00863
00864
00865
00866
00867
00868
00881 template<class T> void ArgList2Vector(CNode* n, NodeOp_t op,
00882 int argNumber, vector<T>& v)
00883 {
00884 if( !n ) {
00885 return;
00886 }
00887 switch( n->GetOp() ) {
00888 case eLIST:
00889 ArgList2Vector<T>(n->Arg<CNode*>(0),op,argNumber,v);
00890 ArgList2Vector<T>(n->Arg<CNode*>(1),op,argNumber,v);
00891 break;
00892 default:
00893 if( n->GetOp() == op ) {
00894 v.push_back(n->Arg<T>(argNumber));
00895 }
00896 break;
00897 }
00898 }
00899
00908 inline void EList2VectorExclude(CNode* n, const set<NodeOp_t>& excludeOps, vector<CNode*>& v)
00909 {
00910 if( !n ) {
00911 return;
00912 }
00913 switch( n->GetOp() ) {
00914 case eELIST:
00915 EList2VectorExclude(n->Arg<CNode*>(0),excludeOps,v);
00916 EList2VectorExclude(n->Arg<CNode*>(1),excludeOps,v);
00917 break;
00918 default:
00919 if( excludeOps.find(n->GetOp()) == excludeOps.end() ) {
00920 v.push_back(n);
00921 }
00922 break;
00923 }
00924 }
00925
00932 inline CNode* Vector2EList(vector<CNode*>& v)
00933 {
00934 CNode* result = NULL;
00935 vector<CNode*>::reverse_iterator ptr;
00936 for( ptr = v.rbegin(); ptr != v.rend(); ++ptr ) {
00937 if( result ) {
00938 result = cELIST(*ptr, result);
00939 } else {
00940 result = *ptr;
00941 }
00942 }
00943 return result;
00944 }
00945
00954 inline int ListCount(CNode* n, NodeOp_t op)
00955 {
00956 int result = 0;
00957 if( !n ) {
00958 return result;
00959 }
00960 switch( n->GetOp() ) {
00961 case eLIST:
00962 case eELIST:
00963 result += ListCount(n->Arg<CNode*>(0),op);
00964 result += ListCount(n->Arg<CNode*>(1),op);
00965 break;
00966 default:
00967 if( n->GetOp() == op ) {
00968 result = 1;
00969 }
00970 break;
00971 }
00972 return result;
00973 }
00974
00981 inline int ListCount(CNode* n)
00982 {
00983 int result = 0;
00984 if( !n ) {
00985 return result;
00986 }
00987 switch( n->GetOp() ) {
00988 case eLIST:
00989 case eELIST:
00990 result += ListCount(n->Arg<CNode*>(0));
00991 result += ListCount(n->Arg<CNode*>(1));
00992 break;
00993 default:
00994 result = 1;
00995 break;
00996 }
00997 return result;
00998 }
00999
01010 inline double s2d( char* s ) {
01011 return atof(s);
01012 }
01013
01022 inline char* d2s( double d, CObstack* heap ) {
01023 char buffer[256];
01024
01025
01026 snprintf( buffer, sizeof(buffer), "%g", d );
01027 char* s = (char*)heap->Alloc(strlen(buffer)+1);
01028 strcpy( s, buffer );
01029 return s;
01030 }
01031
01032
01033
01034
01035
01036 inline CNode* RebalanceRight( CNode* n ) {
01037 if( n == NULL ) {
01038 return n;
01039 }
01040 if( n->GetOp() != eLIST ) {
01041 return n;
01042 }
01043 CNode* result = n;
01044 CNode* parent = NULL;
01045 while( 1 ) {
01046 while( n->Arg<CNode*>(0) && n->Arg<CNode*>(0)->GetOp() == eLIST ) {
01047 CNode* l = n->Arg<CNode*>(0);
01048 CNode* ll = l->Arg<CNode*>(0);
01049 CNode* lr = l->Arg<CNode*>(1);
01050 l->Arg<CNode*>(1) = n;
01051 n->Arg<CNode*>(0) = lr;
01052 n = l;
01053 if( parent ) {
01054 parent->Arg<CNode*>(1) = n;
01055 } else {
01056 result = n;
01057 }
01058 }
01059 if( n->Arg<CNode*>(1) && n->Arg<CNode*>(1)->GetOp() == eLIST ) {
01060 parent = n;
01061 n = n->Arg<CNode*>(1);
01062 } else {
01063 break;
01064 }
01065 }
01066 return result;
01067 }
01068
01069
01070
01071
01072
01073
01074 inline void MeasureDepth( CNode* n, int* count, int* depth )
01075 {
01076 *count = 0;
01077 *depth = 0;
01078 if( !n ) {
01079 return;
01080 }
01081 if( n->GetOp() == eLIST ) {
01082 int count0 = 0;
01083 int depth0 = 0;
01084 int count1 = 0;
01085 int depth1 = 0;
01086 if( n->Arg<CNode*>(0) ) {
01087 MeasureDepth( n->Arg<CNode*>(0), &count0, &depth0 );
01088 depth0++;
01089 }
01090 if( n->Arg<CNode*>(1) ) {
01091 MeasureDepth( n->Arg<CNode*>(1), &count1, &depth1 );
01092 }
01093 *count = count0+count1;
01094 *depth = depth0 > depth1 ? depth0 : depth1;
01095 }
01096 (*count)++;
01097 }
01098
01099
01100
01101
01102
01103
01104 inline CNode_pr cLINK( CNode_pr pr1, CNode* n2 )
01105 {
01106 if( !n2 ) {
01107 return pr1;
01108 } else if( !pr1.tail ) {
01109 CNode_pr pr;
01110 pr.head = n2;
01111 pr.tail = n2;
01112 return pr;
01113 } else if( pr1.tail->GetOp() != eLIST ) {
01114 CNode* t = cLINK( pr1.head, n2 );
01115 CNode_pr pr;
01116 pr.head = t;
01117 pr.tail = t;
01118 return pr;
01119 } else {
01120 pr1.tail->Arg<CNode*>(1) = cLINK(pr1.tail->Arg<CNode*>(1),n2);
01121 CNode_pr pr;
01122 pr.head = pr1.head;
01123 pr.tail = pr1.tail->Arg<CNode*>(1);
01124 return pr;
01125 }
01126 }
01127
01128
01129
01130
01131 inline CNode* cMAX_N( CNode* first, ... )
01132 {
01133 CNode* result = first;
01134 va_list ap;
01135 va_start( ap, first );
01136 while( 1 ) {
01137 CNode* arg = va_arg(ap,CNode*);
01138 if( !arg ) {
01139 break;
01140 }
01141 result = cMAX( result, arg );
01142 }
01143 va_end( ap );
01144 return result;
01145 }
01146
01147 inline CNode* cADD_N( CNode* first, ... )
01148 {
01149 CNode* result = first;
01150 va_list ap;
01151 va_start( ap, first );
01152 while( 1 ) {
01153 CNode* arg = va_arg(ap,CNode*);
01154 if( !arg ) {
01155 break;
01156 }
01157 result = cADD( result, arg );
01158 }
01159 va_end( ap );
01160 return result;
01161 }
01162
01163 inline CNode* cMUL_N( CNode* first, ... )
01164 {
01165 CNode* result = first;
01166 va_list ap;
01167 va_start( ap, first );
01168 while( 1 ) {
01169 CNode* arg = va_arg(ap,CNode*);
01170 if( !arg ) {
01171 break;
01172 }
01173 result = cMUL( result, arg );
01174 }
01175 va_end( ap );
01176 return result;
01177 }
01178
01179 inline CNode* cABSDIFFPLUS1_N( CNode* first, ... )
01180 {
01181 va_list ap;
01182 va_start( ap, first );
01183 CNode* second = va_arg(ap,CNode*);
01184
01185
01186
01187 MASSERT( va_arg(ap,CNode*) == NULL );
01188 va_end( ap );
01189 return cADD(cABSDIFF(first,second),cINT32(1));
01190 }
01191
01192 inline int cMAX( int a1, int a2 )
01193 {
01194 return a1 < a2 ? a2 : a1;
01195 }
01196
01197 inline int cMAX( int a1, int a2, int a3 )
01198 {
01199 return cMAX(a1,cMAX(a2,a3));
01200 }
01201
01202 inline int cADD( int a1, int a2 )
01203 {
01204 return a1 + a2;
01205 }
01206
01207 inline int cMUL( int a1, int a2 )
01208 {
01209 return a1 * a2;
01210 }
01211
01212 inline int cABSDIFFPLUS1( int a1, int a2 )
01213 {
01214 int diff = a1-a2;
01215 return (diff < 0 ? -diff : diff)+1;
01216 }
01217
01218
01219 #endif // CNODE_HPP
01220