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 CParam;
00047 class CFref;
00048 class CVar;
00049 class CNet;
00050 class CPort;
00051 class CPortDir;
00052 class CInstance;
00053 class CFunction;
00054 class CModule;
00055 class CGate;
00056 class CEvent;
00057 class CAttr;
00058 class CBlock;
00059 class CSpecify;
00060 class CNode;
00061 typedef CBlock CScope;
00062 inline char* d2s( double d, CObstack* stack );
00063
00067 enum Edge_t {
00068 eEDGE01 = 0x1,
00069 eEDGE10 = 0x2,
00070 eEDGE0x = 0x4,
00071 eEDGEx1 = 0x8,
00072 eEDGE1x = 0x10,
00073 eEDGEx0 = 0x20,
00074 };
00075
00079 enum DelayMode_t {
00080 eMIN_DELAY,
00081 eTYP_DELAY,
00082 eMAX_DELAY
00083 };
00084
00088 enum Strength_t {
00089 eUNDEFINED = 0,
00090 eSUPPLY,
00091 eSTRONG,
00092 ePULL,
00093 eLARGE,
00094 eWEAK,
00095 eMEDIUM,
00096 eSMALL,
00097 eHIGHZ,
00098 };
00099
00103 struct StrengthPair_t {
00104 Strength_t s0;
00105 Strength_t s1;
00106 };
00107
00108 #define DEFINE_ENUM
00109 #include "cnode_def.h"
00110 #undef DEFINE_ENUM
00111
00112
00119 template<class T>
00120 class CNode_sp {
00121 T* ptr;
00122 public:
00123 CNode_sp( void** np ) { ptr = (T*)np; }
00124 T operator=( T n ) { *ptr = n; return n; }
00125 T operator->() { return *ptr; }
00126 operator T() { return *ptr; }
00127 int operator==( T v ) { return *ptr == v; }
00128 int operator!=( T v ) { return *ptr != v; }
00129 int operator==( CNode_sp<T> p ) { return *ptr == *p.ptr; }
00130 int operator!=( CNode_sp<T> p ) { return *ptr != *p.ptr; }
00131 };
00132
00137 struct CNode_pr {
00138 CNode* head;
00139 CNode* tail;
00140 public:
00141 CNode* operator=( CNode* n ) { head = n; tail = n; return n; }
00142 CNode* operator->() { return head; }
00143 operator CNode*() { return head; }
00144 int operator==( CNode* v ) { return head == v; }
00145 int operator!=( CNode* v ) { return head != v; }
00146 int operator==( CNode_pr p ) { return head == p.head; }
00147 int operator!=( CNode_pr p ) { return head != p.head; }
00148 friend CNode_pr cLINK( CNode_pr pr1, CNode* n2 );
00149 };
00150
00155 struct CNode_triplet {
00156 CNode* first;
00157 CNode* second;
00158 CNode* third;
00159 };
00160
00161
00182 class CNode : public CObject
00183 {
00184 private:
00185 static list<CObstack*> stackList;
00186 static CObstack evalHeap;
00187 static INT32 evalCount;
00188 static CObstack* stack;
00189 static map<CNode*,int> labelCache;
00190 static int labelCacheEnabled;
00191 NodeOp_t op;
00192 void* left;
00193 void* right;
00194 Coord_t loc;
00195 Coord_t *locp;
00196 CNode* attributes;
00197
00198
00199
00200
00201 NodeType_t type;
00202 INT32 width;
00203 int fixedWidth;
00204 private:
00205 int LabelBits( int supressErrorMessages = FALSE );
00206 CNode* FixBits( INT32 newWidth, NodeType_t newType );
00207 void _EvalVector( CVector& v );
00208 double _EvalReal( void );
00209 void FixedWidth( int v ) { fixedWidth = v; }
00210 int FixedWidth() { return fixedWidth; }
00211 int ConditionalWiden();
00212 int WidthFixed();
00213 unsigned NodeMask();
00214 CNode* GetNLeft( void ) { return (CNode*)left; }
00215 CNode* GetNRight( void ) { return (CNode*)right; }
00216 static void _LabelBits( CNode* n, void* arg );
00217 public:
00222 static CObstack* CurrentHeap() { return stack; }
00232 static void UseEvalStack( void ) {
00233 stackList.push_front( stack );
00234 evalCount++;
00235 stack = &evalHeap;
00236 }
00241 static void SetBuildStack( CObstack* aStack ) {
00242 MASSERT( evalCount == 0 );
00243 stackList.push_front( stack );
00244 stack = aStack;
00245 }
00249 static void ResetBuildStack( void ) {
00250 if( stack == &evalHeap ) {
00251 evalCount--;
00252 if( evalCount == 0 ) {
00253 evalHeap.Free( NULL );
00254 }
00255 }
00256 if( stackList.empty() ) {
00257 stack = NULL;
00258 } else {
00259 stack = *stackList.begin();
00260 stackList.pop_front();
00261 }
00262 }
00272 static void EnableLabelCache()
00273 {
00274 labelCacheEnabled = 1;
00275 }
00280 static void DisableAndClearLabelCache()
00281 {
00282 labelCacheEnabled = 0;
00283 labelCache.erase( labelCache.begin(), labelCache.end() );
00284 }
00292 CNode( Coord_t* aLoc, NodeOp_t aOp );
00297 Coord_t* GetCoord() { return locp; }
00302 NodeOp_t GetOp() { return op; }
00309 void SetOp( NodeOp_t aOp ) {
00310 int oldCount = ArgCount();
00311 op = aOp;
00312 MASSERT( oldCount == ArgCount() );
00313 }
00319 unsigned Hash();
00325 template<class T> CNode_sp<T> Arg( int index );
00330 int ArgCount( void );
00338 CNode* Clone( CObstack* heap = stack );
00343 int Precedence();
00350 void PostVisit1( void (*callback)(CNode*,void*), void* data );
00359 CNode* PostSubVisit1( CNode* (*callback)(CNode*,void*),
00360 void* data );
00368 void PreVisit1( int (*callback)(CNode*,void*), void* data );
00377 CNode* Simplify( INT32 newWidth, NodeType_t newType );
00387 int IsNonX( int integerIsNonX = 0, char* exclude = NULL );
00393 int IsConstant();
00403 int IsEvaluateable();
00409 int IsVolatile( void );
00414 INT32 EvalINT32();
00421 void EvalVector( CVector& v );
00430 void EvalVector( CVector& v, INT32 newWidth, NodeType_t newType );
00436 double EvalReal( void );
00441 void Dump( FILE* f );
00447 int IsWidthConstant( void );
00453 int IsWidthVolatile( void );
00463 int IsWidthEvaluateable( void );
00468 CNode* GetWidthExp( void );
00474 INT32 GetWidth( void ) { LabelBits(TRUE); return width; }
00479 int IsScalar( void ) { LabelBits(TRUE); return width==1; }
00484 int IsVector( void ) { LabelBits(TRUE); return width>1; }
00489 int IsReal( void ) { LabelBits(TRUE); return type==eR; }
00494 CNode* GetAttributes() { return attributes; }
00499 void SetAttributes( CNode* attr ) { attributes = attr; }
00507 int HasAttribute( const char* name, CNode* n=NULL, int init = 1 );
00515 CAttr* GetAttribute( const char* name, CNode* n=NULL, int init = 1 );
00520 NodeType_t GetNodeType( void ) { LabelBits(TRUE); return type; }
00521 };
00522
00523
00524
00525
00526
00527
00528
00529 template<class T> CNode_sp<T> CNode::Arg(int index)
00530 {
00531 switch( ArgCount() ) {
00532 case 1:
00533 switch( index ) {
00534 case 0:
00535 return CNode_sp<T>(&left);
00536 default:
00537 MASSERT( FALSE );
00538 return NULL;
00539 }
00540 case 2:
00541 switch( index ) {
00542 case 0:
00543 return CNode_sp<T>(&left);
00544 case 1:
00545 return CNode_sp<T>(&right);
00546 default:
00547 MASSERT( FALSE );
00548 return NULL;
00549 }
00550 case 3:
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>(&right);
00558 default:
00559 MASSERT( FALSE );
00560 return NULL;
00561 }
00562 case 4:
00563 switch( index ) {
00564 case 0:
00565 return CNode_sp<T>(&GetNLeft()->left);
00566 case 1:
00567 return CNode_sp<T>(&GetNLeft()->right);
00568 case 2:
00569 return CNode_sp<T>(&GetNRight()->left);
00570 case 3:
00571 return CNode_sp<T>(&GetNRight()->right);
00572 default:
00573 MASSERT( FALSE );
00574 return NULL;
00575 }
00576 case 5:
00577 switch( index ) {
00578 case 0:
00579 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00580 case 1:
00581 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00582 case 2:
00583 return CNode_sp<T>(&GetNLeft()->right);
00584 case 3:
00585 return CNode_sp<T>(&GetNRight()->left);
00586 case 4:
00587 return CNode_sp<T>(&GetNRight()->right);
00588 default:
00589 MASSERT( FALSE );
00590 return NULL;
00591 }
00592 case 6:
00593 switch( index ) {
00594 case 0:
00595 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00596 case 1:
00597 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00598 case 2:
00599 return CNode_sp<T>(&GetNLeft()->GetNRight()->left);
00600 case 3:
00601 return CNode_sp<T>(&GetNLeft()->GetNRight()->right);
00602 case 4:
00603 return CNode_sp<T>(&GetNRight()->left);
00604 case 5:
00605 return CNode_sp<T>(&GetNRight()->right);
00606 default:
00607 MASSERT( FALSE );
00608 return NULL;
00609 }
00610 case 7:
00611 switch( index ) {
00612 case 0:
00613 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00614 case 1:
00615 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00616 case 2:
00617 return CNode_sp<T>(&GetNLeft()->GetNRight()->left);
00618 case 3:
00619 return CNode_sp<T>(&GetNLeft()->GetNRight()->right);
00620 case 4:
00621 return CNode_sp<T>(&GetNRight()->GetNLeft()->left);
00622 case 5:
00623 return CNode_sp<T>(&GetNRight()->GetNLeft()->right);
00624 case 6:
00625 return CNode_sp<T>(&GetNRight()->right);
00626 default:
00627 MASSERT( FALSE );
00628 return NULL;
00629 }
00630 case 8:
00631 switch( index ) {
00632 case 0:
00633 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00634 case 1:
00635 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00636 case 2:
00637 return CNode_sp<T>(&GetNLeft()->GetNRight()->left);
00638 case 3:
00639 return CNode_sp<T>(&GetNLeft()->GetNRight()->right);
00640 case 4:
00641 return CNode_sp<T>(&GetNRight()->GetNLeft()->left);
00642 case 5:
00643 return CNode_sp<T>(&GetNRight()->GetNLeft()->right);
00644 case 6:
00645 return CNode_sp<T>(&GetNRight()->GetNRight()->left);
00646 case 7:
00647 return CNode_sp<T>(&GetNRight()->GetNRight()->right);
00648 default:
00649 MASSERT( FALSE );
00650 return NULL;
00651 }
00652
00653 default:
00654 MASSERT( FALSE );
00655 }
00656 }
00657 int Equivalent( CNode* a, CNode* b );
00658
00659
00660
00661
00662 inline void Add( double* r, double* a, double* b )
00663 {
00664 *r = *a + *b;
00665 }
00666
00667 inline void Sub( double* r, double* a, double* b )
00668 {
00669 *r = *a - *b;
00670 }
00671
00672 inline void Mul( double* r, double* a, double* b )
00673 {
00674 *r = *a * *b;
00675 }
00676
00677 inline void Div( double* r, double* a, double* b )
00678 {
00679 *r = *a / *b;
00680 }
00681
00682 inline void Neg( double* r, double* a )
00683 {
00684 *r = - *a;
00685 }
00686
00687 inline void Plus( double* r, double* a )
00688 {
00689 *r = *a;
00690 }
00691
00692 inline void Pow( double* r, double* a, double* b )
00693 {
00694 *r = pow(*a,*b);
00695 }
00696
00697
00698
00699
00700
00701 #define ILLEGAL_OP2(op) \
00702 inline void op( double*, double*, double* )\
00703 { fatal( NULL, #op " is illegal for reals" ); }
00704
00705 #define ILLEGAL_OP1(op) \
00706 inline void op( double*, double* )\
00707 { fatal( NULL, #op " is illegal for reals" ); }
00708
00709 ILLEGAL_OP2(Rsh);
00710 ILLEGAL_OP2(Lsh);
00711
00712 ILLEGAL_OP2(Rep);
00713 ILLEGAL_OP2(Mod);
00714 ILLEGAL_OP2(And);
00715 ILLEGAL_OP2(Xor);
00716 ILLEGAL_OP2(Xnor);
00717 ILLEGAL_OP2(Or);
00718 ILLEGAL_OP2(Lor);
00719 ILLEGAL_OP2(Land);
00720 ILLEGAL_OP1(Com);
00721 ILLEGAL_OP1(Rand);
00722 ILLEGAL_OP1(Rnand);
00723 ILLEGAL_OP1(Ror);
00724 ILLEGAL_OP1(Rnor);
00725 ILLEGAL_OP1(Rxor);
00726 ILLEGAL_OP1(Rxnor);
00727
00728 #define DEFINE_CONSTRUCTOR
00729 #include "cnode_def.h"
00730 #undef DEFINE_CONSTRUCTOR
00731
00732
00733
00734
00735
00742 inline CNode* cVECTOR( CVector& vec )
00743 {
00744 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), vec.GetWidth() );
00745 CNode* n;
00746 *v = vec;
00747 v->SetPreferredBase( vec.GetPreferredBase() );
00748 n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00749 n->Arg<CVector*>(0) = v;
00750 return n;
00751 }
00752
00759 inline CNode* cSTRING( const char* s )
00760 {
00761 int len = strlen( s );
00762 if( !len ) {
00763 len = 1;
00764 }
00765 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), len*8 );
00766 v->LoadString( s );
00767 CNode* n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00768 n->Arg<CVector*>(0) = v;
00769 return n;
00770 }
00771
00778 inline CNode* cINT32( INT32 i )
00779 {
00780 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), 32 );
00781 CNode* n;
00782 *v = i;
00783 v->Sized(FALSE);
00784 v->Signed(TRUE);
00785 v->Based(FALSE);
00786 n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00787 n->Arg<CVector*>(0) = v;
00788 return n;
00789 }
00790
00797 inline CNode* cREAL( double number )
00798 {
00799 CNode* node = new(CNode::CurrentHeap()) CNode( NULL, eRCONSTANT );
00800 node->Arg<char*>(0) = d2s(number,CNode::CurrentHeap());
00801 return node;
00802 }
00803
00811 inline CNode* cELINK( CNode* n1, CNode* n2 )
00812 {
00813 if( n1 == NULL ) {
00814 return n2;
00815 } else if( n2 == NULL ) {
00816 return n1;
00817 }
00818 return cELIST( n1, n2 );
00819 }
00820
00828 inline CNode* cABS( CNode* a )
00829 {
00830 CNode* a1 = a->Clone();
00831 CNode* a2 = a->Clone();
00832 CNode* c = cGE(a,cINT32(0));
00833 return cHOOK( c, a1, cNEG( a2) );
00834 }
00835
00844 inline CNode* cABSDIFF( CNode* a, CNode* b )
00845 {
00846 return cABS( cSUB( a, b ) );
00847 }
00848
00857 inline CNode* cLINK( CNode* n1, CNode* n2 )
00858 {
00859 if( n1 == NULL ) {
00860 return n2;
00861 } else if( n2 == NULL ) {
00862 return n1;
00863 }
00864 return cLIST( n1, n2 );
00865 }
00866
00875 inline CNode* cMAX( CNode* n1, CNode* n2 )
00876 {
00877 CNode* cond = cLT(n2->Clone(),n1->Clone());
00878 return cHOOK(cond,n1,n2);
00879 }
00880
00881
00882
00883
00884
00885
00898 template<class T> void ArgList2Vector(CNode* n, NodeOp_t op,
00899 int argNumber, vector<T>& v)
00900 {
00901 if( !n ) {
00902 return;
00903 }
00904 switch( n->GetOp() ) {
00905 case eLIST:
00906 ArgList2Vector<T>(n->Arg<CNode*>(0),op,argNumber,v);
00907 ArgList2Vector<T>(n->Arg<CNode*>(1),op,argNumber,v);
00908 break;
00909 default:
00910 if( n->GetOp() == op ) {
00911 v.push_back(n->Arg<T>(argNumber));
00912 }
00913 break;
00914 }
00915 }
00916
00925 inline void EList2VectorExclude(CNode* n, const set<NodeOp_t>& excludeOps, vector<CNode*>& v)
00926 {
00927 if( !n ) {
00928 return;
00929 }
00930 switch( n->GetOp() ) {
00931 case eELIST:
00932 EList2VectorExclude(n->Arg<CNode*>(0),excludeOps,v);
00933 EList2VectorExclude(n->Arg<CNode*>(1),excludeOps,v);
00934 break;
00935 default:
00936 if( excludeOps.find(n->GetOp()) == excludeOps.end() ) {
00937 v.push_back(n);
00938 }
00939 break;
00940 }
00941 }
00942
00951 inline void List2VectorExclude(CNode* n, const set<NodeOp_t>& excludeOps, vector<CNode*>& v)
00952 {
00953 if( !n ) {
00954 return;
00955 }
00956 switch( n->GetOp() ) {
00957 case eLIST:
00958 List2VectorExclude(n->Arg<CNode*>(0),excludeOps,v);
00959 List2VectorExclude(n->Arg<CNode*>(1),excludeOps,v);
00960 break;
00961 default:
00962 if( excludeOps.find(n->GetOp()) == excludeOps.end() ) {
00963 v.push_back(n);
00964 }
00965 break;
00966 }
00967 }
00968
00975 inline CNode* Vector2EList(vector<CNode*>& v)
00976 {
00977 CNode* result = NULL;
00978 vector<CNode*>::reverse_iterator ptr;
00979 for( ptr = v.rbegin(); ptr != v.rend(); ++ptr ) {
00980 if( result ) {
00981 result = cELIST(*ptr, result);
00982 } else {
00983 result = *ptr;
00984 }
00985 }
00986 return result;
00987 }
00988
00997 inline int ListCount(CNode* n, NodeOp_t op)
00998 {
00999 int result = 0;
01000 if( !n ) {
01001 return result;
01002 }
01003 switch( n->GetOp() ) {
01004 case eLIST:
01005 case eELIST:
01006 result += ListCount(n->Arg<CNode*>(0),op);
01007 result += ListCount(n->Arg<CNode*>(1),op);
01008 break;
01009 default:
01010 if( n->GetOp() == op ) {
01011 result = 1;
01012 }
01013 break;
01014 }
01015 return result;
01016 }
01017
01024 inline int ListCount(CNode* n)
01025 {
01026 int result = 0;
01027 if( !n ) {
01028 return result;
01029 }
01030 switch( n->GetOp() ) {
01031 case eLIST:
01032 case eELIST:
01033 result += ListCount(n->Arg<CNode*>(0));
01034 result += ListCount(n->Arg<CNode*>(1));
01035 break;
01036 default:
01037 result = 1;
01038 break;
01039 }
01040 return result;
01041 }
01042
01053 inline double s2d( char* s ) {
01054 return atof(s);
01055 }
01056
01065 inline char* d2s( double d, CObstack* heap ) {
01066 char buffer[256];
01067
01068
01069 snprintf( buffer, sizeof(buffer), "%g", d );
01070 char* s = (char*)heap->Alloc(strlen(buffer)+1);
01071 strcpy( s, buffer );
01072 return s;
01073 }
01074
01075
01076
01077
01078
01079 inline CNode* RebalanceRight( CNode* n ) {
01080 if( n == NULL ) {
01081 return n;
01082 }
01083 if( n->GetOp() != eLIST ) {
01084 return n;
01085 }
01086 CNode* result = n;
01087 CNode* parent = NULL;
01088 while( 1 ) {
01089 while( n->Arg<CNode*>(0) && n->Arg<CNode*>(0)->GetOp() == eLIST ) {
01090 CNode* l = n->Arg<CNode*>(0);
01091 CNode* ll = l->Arg<CNode*>(0);
01092 CNode* lr = l->Arg<CNode*>(1);
01093 l->Arg<CNode*>(1) = n;
01094 n->Arg<CNode*>(0) = lr;
01095 n = l;
01096 if( parent ) {
01097 parent->Arg<CNode*>(1) = n;
01098 } else {
01099 result = n;
01100 }
01101 }
01102 if( n->Arg<CNode*>(1) && n->Arg<CNode*>(1)->GetOp() == eLIST ) {
01103 parent = n;
01104 n = n->Arg<CNode*>(1);
01105 } else {
01106 break;
01107 }
01108 }
01109 return result;
01110 }
01111
01112
01113
01114
01115
01116
01117 inline void MeasureDepth( CNode* n, int* count, int* depth )
01118 {
01119 *count = 0;
01120 *depth = 0;
01121 if( !n ) {
01122 return;
01123 }
01124 if( n->GetOp() == eLIST ) {
01125 int count0 = 0;
01126 int depth0 = 0;
01127 int count1 = 0;
01128 int depth1 = 0;
01129 if( n->Arg<CNode*>(0) ) {
01130 MeasureDepth( n->Arg<CNode*>(0), &count0, &depth0 );
01131 depth0++;
01132 }
01133 if( n->Arg<CNode*>(1) ) {
01134 MeasureDepth( n->Arg<CNode*>(1), &count1, &depth1 );
01135 }
01136 *count = count0+count1;
01137 *depth = depth0 > depth1 ? depth0 : depth1;
01138 }
01139 (*count)++;
01140 }
01141
01142
01143
01144
01145
01146
01147 inline CNode_pr cLINK( CNode_pr pr1, CNode* n2 )
01148 {
01149 if( !n2 ) {
01150 return pr1;
01151 } else if( !pr1.tail ) {
01152 CNode_pr pr;
01153 pr.head = n2;
01154 pr.tail = n2;
01155 return pr;
01156 } else if( pr1.tail->GetOp() != eLIST ) {
01157 CNode* t = cLINK( pr1.head, n2 );
01158 CNode_pr pr;
01159 pr.head = t;
01160 pr.tail = t;
01161 return pr;
01162 } else {
01163 pr1.tail->Arg<CNode*>(1) = cLINK(pr1.tail->Arg<CNode*>(1),n2);
01164 CNode_pr pr;
01165 pr.head = pr1.head;
01166 pr.tail = pr1.tail->Arg<CNode*>(1);
01167 return pr;
01168 }
01169 }
01170
01171
01172
01173
01174 inline CNode* cMAX_N( CNode* first, ... )
01175 {
01176 CNode* result = first;
01177 va_list ap;
01178 va_start( ap, first );
01179 while( 1 ) {
01180 CNode* arg = va_arg(ap,CNode*);
01181 if( !arg ) {
01182 break;
01183 }
01184 result = cMAX( result, arg );
01185 }
01186 va_end( ap );
01187 return result;
01188 }
01189
01190 inline CNode* cADD_N( CNode* first, ... )
01191 {
01192 CNode* result = first;
01193 va_list ap;
01194 va_start( ap, first );
01195 while( 1 ) {
01196 CNode* arg = va_arg(ap,CNode*);
01197 if( !arg ) {
01198 break;
01199 }
01200 result = cADD( result, arg );
01201 }
01202 va_end( ap );
01203 return result;
01204 }
01205
01206 inline CNode* cMUL_N( CNode* first, ... )
01207 {
01208 CNode* result = first;
01209 va_list ap;
01210 va_start( ap, first );
01211 while( 1 ) {
01212 CNode* arg = va_arg(ap,CNode*);
01213 if( !arg ) {
01214 break;
01215 }
01216 result = cMUL( result, arg );
01217 }
01218 va_end( ap );
01219 return result;
01220 }
01221
01222 inline CNode* cABSDIFFPLUS1_N( CNode* first, ... )
01223 {
01224 va_list ap;
01225 va_start( ap, first );
01226 CNode* second = va_arg(ap,CNode*);
01227
01228
01229
01230 MASSERT( va_arg(ap,CNode*) == NULL );
01231 va_end( ap );
01232 return cADD(cABSDIFF(first,second),cINT32(1));
01233 }
01234
01235 inline int cMAX( int a1, int a2 )
01236 {
01237 return a1 < a2 ? a2 : a1;
01238 }
01239
01240 inline int cMAX( int a1, int a2, int a3 )
01241 {
01242 return cMAX(a1,cMAX(a2,a3));
01243 }
01244
01245 inline int cADD( int a1, int a2 )
01246 {
01247 return a1 + a2;
01248 }
01249
01250 inline int cMUL( int a1, int a2 )
01251 {
01252 return a1 * a2;
01253 }
01254
01255 inline int cABSDIFFPLUS1( int a1, int a2 )
01256 {
01257 int diff = a1-a2;
01258 return (diff < 0 ? -diff : diff)+1;
01259 }
01260
01261
01262 #endif // CNODE_HPP
01263