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 Plus( double* r, double* a )
00676 {
00677 *r = *a;
00678 }
00679
00680 inline void Pow( double* r, double* a, double* b )
00681 {
00682 *r = pow(*a,*b);
00683 }
00684
00685
00686
00687
00688
00689 #define ILLEGAL_OP2(op) \
00690 inline void op( double*, double*, double* )\
00691 { fatal( NULL, #op " is illegal for reals" ); }
00692
00693 #define ILLEGAL_OP1(op) \
00694 inline void op( double*, double* )\
00695 { fatal( NULL, #op " is illegal for reals" ); }
00696
00697 ILLEGAL_OP2(Rsh);
00698 ILLEGAL_OP2(Lsh);
00699
00700 ILLEGAL_OP2(Rep);
00701 ILLEGAL_OP2(Mod);
00702 ILLEGAL_OP2(And);
00703 ILLEGAL_OP2(Xor);
00704 ILLEGAL_OP2(Xnor);
00705 ILLEGAL_OP2(Or);
00706 ILLEGAL_OP2(Lor);
00707 ILLEGAL_OP2(Land);
00708 ILLEGAL_OP1(Com);
00709 ILLEGAL_OP1(Rand);
00710 ILLEGAL_OP1(Rnand);
00711 ILLEGAL_OP1(Ror);
00712 ILLEGAL_OP1(Rnor);
00713 ILLEGAL_OP1(Rxor);
00714 ILLEGAL_OP1(Rxnor);
00715
00716 #define DEFINE_CONSTRUCTOR
00717 #include "cnode_def.h"
00718 #undef DEFINE_CONSTRUCTOR
00719
00720
00721
00722
00723
00730 inline CNode* cVECTOR( CVector& vec )
00731 {
00732 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), vec.GetWidth() );
00733 CNode* n;
00734 *v = vec;
00735 v->SetPreferredBase( vec.GetPreferredBase() );
00736 n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00737 n->Arg<CVector*>(0) = v;
00738 return n;
00739 }
00740
00747 inline CNode* cSTRING( const char* s )
00748 {
00749 int len = strlen( s );
00750 if( !len ) {
00751 len = 1;
00752 }
00753 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), len*8 );
00754 v->LoadString( s );
00755 CNode* n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00756 n->Arg<CVector*>(0) = v;
00757 return n;
00758 }
00759
00766 inline CNode* cINT32( INT32 i )
00767 {
00768 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), 32 );
00769 CNode* n;
00770 *v = i;
00771 v->Sized(FALSE);
00772 v->Signed(TRUE);
00773 v->Based(FALSE);
00774 n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00775 n->Arg<CVector*>(0) = v;
00776 return n;
00777 }
00778
00785 inline CNode* cREAL( double number )
00786 {
00787 CNode* node = new(CNode::CurrentHeap()) CNode( NULL, eRCONSTANT );
00788 node->Arg<char*>(0) = d2s(number,CNode::CurrentHeap());
00789 return node;
00790 }
00791
00799 inline CNode* cELINK( CNode* n1, CNode* n2 )
00800 {
00801 if( n1 == NULL ) {
00802 return n2;
00803 } else if( n2 == NULL ) {
00804 return n1;
00805 }
00806 return cELIST( n1, n2 );
00807 }
00808
00816 inline CNode* cABS( CNode* a )
00817 {
00818 CNode* a1 = a->Clone();
00819 CNode* a2 = a->Clone();
00820 CNode* c = cGE(a,cINT32(0));
00821 return cHOOK( c, a1, cNEG( a2) );
00822 }
00823
00832 inline CNode* cABSDIFF( CNode* a, CNode* b )
00833 {
00834 return cABS( cSUB( a, b ) );
00835 }
00836
00845 inline CNode* cLINK( CNode* n1, CNode* n2 )
00846 {
00847 if( n1 == NULL ) {
00848 return n2;
00849 } else if( n2 == NULL ) {
00850 return n1;
00851 }
00852 return cLIST( n1, n2 );
00853 }
00854
00863 inline CNode* cMAX( CNode* n1, CNode* n2 )
00864 {
00865 CNode* cond = cLT(n2->Clone(),n1->Clone());
00866 return cHOOK(cond,n1,n2);
00867 }
00868
00869
00870
00871
00872
00873
00886 template<class T> void ArgList2Vector(CNode* n, NodeOp_t op,
00887 int argNumber, vector<T>& v)
00888 {
00889 if( !n ) {
00890 return;
00891 }
00892 switch( n->GetOp() ) {
00893 case eLIST:
00894 ArgList2Vector<T>(n->Arg<CNode*>(0),op,argNumber,v);
00895 ArgList2Vector<T>(n->Arg<CNode*>(1),op,argNumber,v);
00896 break;
00897 default:
00898 if( n->GetOp() == op ) {
00899 v.push_back(n->Arg<T>(argNumber));
00900 }
00901 break;
00902 }
00903 }
00904
00913 inline void EList2VectorExclude(CNode* n, const set<NodeOp_t>& excludeOps, vector<CNode*>& v)
00914 {
00915 if( !n ) {
00916 return;
00917 }
00918 switch( n->GetOp() ) {
00919 case eELIST:
00920 EList2VectorExclude(n->Arg<CNode*>(0),excludeOps,v);
00921 EList2VectorExclude(n->Arg<CNode*>(1),excludeOps,v);
00922 break;
00923 default:
00924 if( excludeOps.find(n->GetOp()) == excludeOps.end() ) {
00925 v.push_back(n);
00926 }
00927 break;
00928 }
00929 }
00930
00939 inline void List2VectorExclude(CNode* n, const set<NodeOp_t>& excludeOps, vector<CNode*>& v)
00940 {
00941 if( !n ) {
00942 return;
00943 }
00944 switch( n->GetOp() ) {
00945 case eLIST:
00946 List2VectorExclude(n->Arg<CNode*>(0),excludeOps,v);
00947 List2VectorExclude(n->Arg<CNode*>(1),excludeOps,v);
00948 break;
00949 default:
00950 if( excludeOps.find(n->GetOp()) == excludeOps.end() ) {
00951 v.push_back(n);
00952 }
00953 break;
00954 }
00955 }
00956
00963 inline CNode* Vector2EList(vector<CNode*>& v)
00964 {
00965 CNode* result = NULL;
00966 vector<CNode*>::reverse_iterator ptr;
00967 for( ptr = v.rbegin(); ptr != v.rend(); ++ptr ) {
00968 if( result ) {
00969 result = cELIST(*ptr, result);
00970 } else {
00971 result = *ptr;
00972 }
00973 }
00974 return result;
00975 }
00976
00985 inline int ListCount(CNode* n, NodeOp_t op)
00986 {
00987 int result = 0;
00988 if( !n ) {
00989 return result;
00990 }
00991 switch( n->GetOp() ) {
00992 case eLIST:
00993 case eELIST:
00994 result += ListCount(n->Arg<CNode*>(0),op);
00995 result += ListCount(n->Arg<CNode*>(1),op);
00996 break;
00997 default:
00998 if( n->GetOp() == op ) {
00999 result = 1;
01000 }
01001 break;
01002 }
01003 return result;
01004 }
01005
01012 inline int ListCount(CNode* n)
01013 {
01014 int result = 0;
01015 if( !n ) {
01016 return result;
01017 }
01018 switch( n->GetOp() ) {
01019 case eLIST:
01020 case eELIST:
01021 result += ListCount(n->Arg<CNode*>(0));
01022 result += ListCount(n->Arg<CNode*>(1));
01023 break;
01024 default:
01025 result = 1;
01026 break;
01027 }
01028 return result;
01029 }
01030
01041 inline double s2d( char* s ) {
01042 return atof(s);
01043 }
01044
01053 inline char* d2s( double d, CObstack* heap ) {
01054 char buffer[256];
01055
01056
01057 snprintf( buffer, sizeof(buffer), "%g", d );
01058 char* s = (char*)heap->Alloc(strlen(buffer)+1);
01059 strcpy( s, buffer );
01060 return s;
01061 }
01062
01063
01064
01065
01066
01067 inline CNode* RebalanceRight( CNode* n ) {
01068 if( n == NULL ) {
01069 return n;
01070 }
01071 if( n->GetOp() != eLIST ) {
01072 return n;
01073 }
01074 CNode* result = n;
01075 CNode* parent = NULL;
01076 while( 1 ) {
01077 while( n->Arg<CNode*>(0) && n->Arg<CNode*>(0)->GetOp() == eLIST ) {
01078 CNode* l = n->Arg<CNode*>(0);
01079 CNode* ll = l->Arg<CNode*>(0);
01080 CNode* lr = l->Arg<CNode*>(1);
01081 l->Arg<CNode*>(1) = n;
01082 n->Arg<CNode*>(0) = lr;
01083 n = l;
01084 if( parent ) {
01085 parent->Arg<CNode*>(1) = n;
01086 } else {
01087 result = n;
01088 }
01089 }
01090 if( n->Arg<CNode*>(1) && n->Arg<CNode*>(1)->GetOp() == eLIST ) {
01091 parent = n;
01092 n = n->Arg<CNode*>(1);
01093 } else {
01094 break;
01095 }
01096 }
01097 return result;
01098 }
01099
01100
01101
01102
01103
01104
01105 inline void MeasureDepth( CNode* n, int* count, int* depth )
01106 {
01107 *count = 0;
01108 *depth = 0;
01109 if( !n ) {
01110 return;
01111 }
01112 if( n->GetOp() == eLIST ) {
01113 int count0 = 0;
01114 int depth0 = 0;
01115 int count1 = 0;
01116 int depth1 = 0;
01117 if( n->Arg<CNode*>(0) ) {
01118 MeasureDepth( n->Arg<CNode*>(0), &count0, &depth0 );
01119 depth0++;
01120 }
01121 if( n->Arg<CNode*>(1) ) {
01122 MeasureDepth( n->Arg<CNode*>(1), &count1, &depth1 );
01123 }
01124 *count = count0+count1;
01125 *depth = depth0 > depth1 ? depth0 : depth1;
01126 }
01127 (*count)++;
01128 }
01129
01130
01131
01132
01133
01134
01135 inline CNode_pr cLINK( CNode_pr pr1, CNode* n2 )
01136 {
01137 if( !n2 ) {
01138 return pr1;
01139 } else if( !pr1.tail ) {
01140 CNode_pr pr;
01141 pr.head = n2;
01142 pr.tail = n2;
01143 return pr;
01144 } else if( pr1.tail->GetOp() != eLIST ) {
01145 CNode* t = cLINK( pr1.head, n2 );
01146 CNode_pr pr;
01147 pr.head = t;
01148 pr.tail = t;
01149 return pr;
01150 } else {
01151 pr1.tail->Arg<CNode*>(1) = cLINK(pr1.tail->Arg<CNode*>(1),n2);
01152 CNode_pr pr;
01153 pr.head = pr1.head;
01154 pr.tail = pr1.tail->Arg<CNode*>(1);
01155 return pr;
01156 }
01157 }
01158
01159
01160
01161
01162 inline CNode* cMAX_N( CNode* first, ... )
01163 {
01164 CNode* result = first;
01165 va_list ap;
01166 va_start( ap, first );
01167 while( 1 ) {
01168 CNode* arg = va_arg(ap,CNode*);
01169 if( !arg ) {
01170 break;
01171 }
01172 result = cMAX( result, arg );
01173 }
01174 va_end( ap );
01175 return result;
01176 }
01177
01178 inline CNode* cADD_N( CNode* first, ... )
01179 {
01180 CNode* result = first;
01181 va_list ap;
01182 va_start( ap, first );
01183 while( 1 ) {
01184 CNode* arg = va_arg(ap,CNode*);
01185 if( !arg ) {
01186 break;
01187 }
01188 result = cADD( result, arg );
01189 }
01190 va_end( ap );
01191 return result;
01192 }
01193
01194 inline CNode* cMUL_N( CNode* first, ... )
01195 {
01196 CNode* result = first;
01197 va_list ap;
01198 va_start( ap, first );
01199 while( 1 ) {
01200 CNode* arg = va_arg(ap,CNode*);
01201 if( !arg ) {
01202 break;
01203 }
01204 result = cMUL( result, arg );
01205 }
01206 va_end( ap );
01207 return result;
01208 }
01209
01210 inline CNode* cABSDIFFPLUS1_N( CNode* first, ... )
01211 {
01212 va_list ap;
01213 va_start( ap, first );
01214 CNode* second = va_arg(ap,CNode*);
01215
01216
01217
01218 MASSERT( va_arg(ap,CNode*) == NULL );
01219 va_end( ap );
01220 return cADD(cABSDIFF(first,second),cINT32(1));
01221 }
01222
01223 inline int cMAX( int a1, int a2 )
01224 {
01225 return a1 < a2 ? a2 : a1;
01226 }
01227
01228 inline int cMAX( int a1, int a2, int a3 )
01229 {
01230 return cMAX(a1,cMAX(a2,a3));
01231 }
01232
01233 inline int cADD( int a1, int a2 )
01234 {
01235 return a1 + a2;
01236 }
01237
01238 inline int cMUL( int a1, int a2 )
01239 {
01240 return a1 * a2;
01241 }
01242
01243 inline int cABSDIFFPLUS1( int a1, int a2 )
01244 {
01245 int diff = a1-a2;
01246 return (diff < 0 ? -diff : diff)+1;
01247 }
01248
01249
01250 #endif // CNODE_HPP
01251