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; }
00494 int HasAttribute( char* name, CNode* n=NULL, int init = 1 );
00499 NodeType_t GetNodeType( void ) { LabelBits(TRUE); return type; }
00500 };
00501
00502
00503
00504
00505
00506
00507
00508 template<class T> CNode_sp<T> CNode::Arg(int index)
00509 {
00510 switch( ArgCount() ) {
00511 case 1:
00512 switch( index ) {
00513 case 0:
00514 return CNode_sp<T>(&left);
00515 default:
00516 MASSERT( FALSE );
00517 return NULL;
00518 }
00519 case 2:
00520 switch( index ) {
00521 case 0:
00522 return CNode_sp<T>(&left);
00523 case 1:
00524 return CNode_sp<T>(&right);
00525 default:
00526 MASSERT( FALSE );
00527 return NULL;
00528 }
00529 case 3:
00530 switch( index ) {
00531 case 0:
00532 return CNode_sp<T>(&GetNLeft()->left);
00533 case 1:
00534 return CNode_sp<T>(&GetNLeft()->right);
00535 case 2:
00536 return CNode_sp<T>(&right);
00537 default:
00538 MASSERT( FALSE );
00539 return NULL;
00540 }
00541 case 4:
00542 switch( index ) {
00543 case 0:
00544 return CNode_sp<T>(&GetNLeft()->left);
00545 case 1:
00546 return CNode_sp<T>(&GetNLeft()->right);
00547 case 2:
00548 return CNode_sp<T>(&GetNRight()->left);
00549 case 3:
00550 return CNode_sp<T>(&GetNRight()->right);
00551 default:
00552 MASSERT( FALSE );
00553 return NULL;
00554 }
00555 case 5:
00556 switch( index ) {
00557 case 0:
00558 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00559 case 1:
00560 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00561 case 2:
00562 return CNode_sp<T>(&GetNLeft()->right);
00563 case 3:
00564 return CNode_sp<T>(&GetNRight()->left);
00565 case 4:
00566 return CNode_sp<T>(&GetNRight()->right);
00567 default:
00568 MASSERT( FALSE );
00569 return NULL;
00570 }
00571 case 6:
00572 switch( index ) {
00573 case 0:
00574 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00575 case 1:
00576 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00577 case 2:
00578 return CNode_sp<T>(&GetNLeft()->GetNRight()->left);
00579 case 3:
00580 return CNode_sp<T>(&GetNLeft()->GetNRight()->right);
00581 case 4:
00582 return CNode_sp<T>(&GetNRight()->left);
00583 case 5:
00584 return CNode_sp<T>(&GetNRight()->right);
00585 default:
00586 MASSERT( FALSE );
00587 return NULL;
00588 }
00589 case 7:
00590 switch( index ) {
00591 case 0:
00592 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00593 case 1:
00594 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00595 case 2:
00596 return CNode_sp<T>(&GetNLeft()->GetNRight()->left);
00597 case 3:
00598 return CNode_sp<T>(&GetNLeft()->GetNRight()->right);
00599 case 4:
00600 return CNode_sp<T>(&GetNRight()->GetNLeft()->left);
00601 case 5:
00602 return CNode_sp<T>(&GetNRight()->GetNLeft()->right);
00603 case 6:
00604 return CNode_sp<T>(&GetNRight()->right);
00605 default:
00606 MASSERT( FALSE );
00607 return NULL;
00608 }
00609 case 8:
00610 switch( index ) {
00611 case 0:
00612 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00613 case 1:
00614 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00615 case 2:
00616 return CNode_sp<T>(&GetNLeft()->GetNRight()->left);
00617 case 3:
00618 return CNode_sp<T>(&GetNLeft()->GetNRight()->right);
00619 case 4:
00620 return CNode_sp<T>(&GetNRight()->GetNLeft()->left);
00621 case 5:
00622 return CNode_sp<T>(&GetNRight()->GetNLeft()->right);
00623 case 6:
00624 return CNode_sp<T>(&GetNRight()->GetNRight()->left);
00625 case 7:
00626 return CNode_sp<T>(&GetNRight()->GetNRight()->right);
00627 default:
00628 MASSERT( FALSE );
00629 return NULL;
00630 }
00631
00632 default:
00633 MASSERT( FALSE );
00634 }
00635 }
00636 int Equivalent( CNode* a, CNode* b );
00637
00638
00639
00640
00641 inline void Add( double* r, double* a, double* b )
00642 {
00643 *r = *a + *b;
00644 }
00645
00646 inline void Sub( double* r, double* a, double* b )
00647 {
00648 *r = *a - *b;
00649 }
00650
00651 inline void Mul( double* r, double* a, double* b )
00652 {
00653 *r = *a * *b;
00654 }
00655
00656 inline void Div( double* r, double* a, double* b )
00657 {
00658 *r = *a / *b;
00659 }
00660
00661 inline void Neg( double* r, double* a )
00662 {
00663 *r = - *a;
00664 }
00665
00666 inline void Pow( double* r, double* a, double* b )
00667 {
00668 *r = pow(*a,*b);
00669 }
00670
00671
00672
00673
00674
00675 #define ILLEGAL_OP2(op) \
00676 inline void op( double*, double*, double* )\
00677 { fatal( NULL, #op " is illegal for reals" ); }
00678
00679 #define ILLEGAL_OP1(op) \
00680 inline void op( double*, double* )\
00681 { fatal( NULL, #op " is illegal for reals" ); }
00682
00683 ILLEGAL_OP2(Rsh);
00684 ILLEGAL_OP2(Lsh);
00685
00686 ILLEGAL_OP2(Rep);
00687 ILLEGAL_OP2(Mod);
00688 ILLEGAL_OP2(And);
00689 ILLEGAL_OP2(Xor);
00690 ILLEGAL_OP2(Xnor);
00691 ILLEGAL_OP2(Or);
00692 ILLEGAL_OP2(Lor);
00693 ILLEGAL_OP2(Land);
00694 ILLEGAL_OP1(Com);
00695 ILLEGAL_OP1(Rand);
00696 ILLEGAL_OP1(Rnand);
00697 ILLEGAL_OP1(Ror);
00698 ILLEGAL_OP1(Rnor);
00699 ILLEGAL_OP1(Rxor);
00700 ILLEGAL_OP1(Rxnor);
00701
00702 #define DEFINE_CONSTRUCTOR
00703 #include "cnode_def.h"
00704 #undef DEFINE_CONSTRUCTOR
00705
00706
00707
00708
00709
00716 inline CNode* cVECTOR( CVector& vec )
00717 {
00718 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), vec.GetWidth() );
00719 CNode* n;
00720 *v = vec;
00721 v->SetPreferredBase( vec.GetPreferredBase() );
00722 n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00723 n->Arg<CVector*>(0) = v;
00724 return n;
00725 }
00726
00733 inline CNode* cINT32( INT32 i )
00734 {
00735 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), 32 );
00736 CNode* n;
00737 *v = i;
00738 v->Sized(FALSE);
00739 v->Signed(TRUE);
00740 v->Based(FALSE);
00741 n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00742 n->Arg<CVector*>(0) = v;
00743 return n;
00744 }
00745
00752 inline CNode* cREAL( double number )
00753 {
00754 CNode* node = new(CNode::CurrentHeap()) CNode( NULL, eRCONSTANT );
00755 node->Arg<char*>(0) = d2s(number,CNode::CurrentHeap());
00756 return node;
00757 }
00758
00766 inline CNode* cELINK( CNode* n1, CNode* n2 )
00767 {
00768 if( n1 == NULL ) {
00769 return n2;
00770 } else if( n2 == NULL ) {
00771 return n1;
00772 }
00773 return cELIST( n1, n2 );
00774 }
00775
00783 inline CNode* cABS( CNode* a )
00784 {
00785 CNode* a1 = a->Clone();
00786 CNode* a2 = a->Clone();
00787 CNode* c = cGE(a,cINT32(0));
00788 return cHOOK( c, a1, cNEG( a2) );
00789 }
00790
00799 inline CNode* cABSDIFF( CNode* a, CNode* b )
00800 {
00801 return cABS( cSUB( a, b ) );
00802 }
00803
00812 inline CNode* cLINK( CNode* n1, CNode* n2 )
00813 {
00814 if( n1 == NULL ) {
00815 return n2;
00816 } else if( n2 == NULL ) {
00817 return n1;
00818 }
00819 return cLIST( n1, n2 );
00820 }
00821
00830 inline CNode* cMAX( CNode* n1, CNode* n2 )
00831 {
00832 CNode* cond = cLT(n2->Clone(),n1->Clone());
00833 return cHOOK(cond,n1,n2);
00834 }
00835
00836
00837
00838
00839
00840
00853 template<class T> void ArgList2Vector(CNode* n, NodeOp_t op,
00854 int argNumber, vector<T>& v)
00855 {
00856 if( !n ) {
00857 return;
00858 }
00859 switch( n->GetOp() ) {
00860 case eLIST:
00861 ArgList2Vector<T>(n->Arg<CNode*>(0),op,argNumber,v);
00862 ArgList2Vector<T>(n->Arg<CNode*>(1),op,argNumber,v);
00863 break;
00864 default:
00865 if( n->GetOp() == op ) {
00866 v.push_back(n->Arg<T>(argNumber));
00867 }
00868 break;
00869 }
00870 }
00871
00880 inline void EList2VectorExclude(CNode* n, const set<NodeOp_t>& excludeOps, vector<CNode*>& v)
00881 {
00882 if( !n ) {
00883 return;
00884 }
00885 switch( n->GetOp() ) {
00886 case eELIST:
00887 EList2VectorExclude(n->Arg<CNode*>(0),excludeOps,v);
00888 EList2VectorExclude(n->Arg<CNode*>(1),excludeOps,v);
00889 break;
00890 default:
00891 if( excludeOps.find(n->GetOp()) == excludeOps.end() ) {
00892 v.push_back(n);
00893 }
00894 break;
00895 }
00896 }
00897
00904 inline CNode* Vector2EList(vector<CNode*>& v)
00905 {
00906 CNode* result = NULL;
00907 vector<CNode*>::reverse_iterator ptr;
00908 for( ptr = v.rbegin(); ptr != v.rend(); ++ptr ) {
00909 if( result ) {
00910 result = cELIST(*ptr, result);
00911 } else {
00912 result = *ptr;
00913 }
00914 }
00915 return result;
00916 }
00917
00926 inline int ListCount(CNode* n, NodeOp_t op)
00927 {
00928 int result = 0;
00929 if( !n ) {
00930 return result;
00931 }
00932 switch( n->GetOp() ) {
00933 case eLIST:
00934 case eELIST:
00935 result += ListCount(n->Arg<CNode*>(0),op);
00936 result += ListCount(n->Arg<CNode*>(1),op);
00937 break;
00938 default:
00939 if( n->GetOp() == op ) {
00940 result = 1;
00941 }
00942 break;
00943 }
00944 return result;
00945 }
00946
00953 inline int ListCount(CNode* n)
00954 {
00955 int result = 0;
00956 if( !n ) {
00957 return result;
00958 }
00959 switch( n->GetOp() ) {
00960 case eLIST:
00961 case eELIST:
00962 result += ListCount(n->Arg<CNode*>(0));
00963 result += ListCount(n->Arg<CNode*>(1));
00964 break;
00965 default:
00966 result = 1;
00967 break;
00968 }
00969 return result;
00970 }
00971
00982 inline double s2d( char* s ) {
00983 return atof(s);
00984 }
00985
00994 inline char* d2s( double d, CObstack* heap ) {
00995 char buffer[256];
00996
00997
00998 snprintf( buffer, sizeof(buffer), "%g", d );
00999 char* s = (char*)heap->Alloc(strlen(buffer)+1);
01000 strcpy( s, buffer );
01001 return s;
01002 }
01003
01004
01005
01006
01007
01008 inline CNode* RebalanceRight( CNode* n ) {
01009 if( n == NULL ) {
01010 return n;
01011 }
01012 if( n->GetOp() != eLIST ) {
01013 return n;
01014 }
01015 CNode* result = n;
01016 CNode* parent = NULL;
01017 while( 1 ) {
01018 while( n->Arg<CNode*>(0) && n->Arg<CNode*>(0)->GetOp() == eLIST ) {
01019 CNode* l = n->Arg<CNode*>(0);
01020 CNode* ll = l->Arg<CNode*>(0);
01021 CNode* lr = l->Arg<CNode*>(1);
01022 l->Arg<CNode*>(1) = n;
01023 n->Arg<CNode*>(0) = lr;
01024 n = l;
01025 if( parent ) {
01026 parent->Arg<CNode*>(1) = n;
01027 } else {
01028 result = n;
01029 }
01030 }
01031 if( n->Arg<CNode*>(1) && n->Arg<CNode*>(1)->GetOp() == eLIST ) {
01032 parent = n;
01033 n = n->Arg<CNode*>(1);
01034 } else {
01035 break;
01036 }
01037 }
01038 return result;
01039 }
01040
01041
01042
01043
01044
01045
01046 inline void MeasureDepth( CNode* n, int* count, int* depth )
01047 {
01048 *count = 0;
01049 *depth = 0;
01050 if( !n ) {
01051 return;
01052 }
01053 if( n->GetOp() == eLIST ) {
01054 int count0 = 0;
01055 int depth0 = 0;
01056 int count1 = 0;
01057 int depth1 = 0;
01058 if( n->Arg<CNode*>(0) ) {
01059 MeasureDepth( n->Arg<CNode*>(0), &count0, &depth0 );
01060 depth0++;
01061 }
01062 if( n->Arg<CNode*>(1) ) {
01063 MeasureDepth( n->Arg<CNode*>(1), &count1, &depth1 );
01064 }
01065 *count = count0+count1;
01066 *depth = depth0 > depth1 ? depth0 : depth1;
01067 }
01068 (*count)++;
01069 }
01070
01071
01072
01073
01074
01075
01076 inline CNode_pr cLINK( CNode_pr pr1, CNode* n2 )
01077 {
01078 if( !n2 ) {
01079 return pr1;
01080 } else if( !pr1.tail ) {
01081 CNode_pr pr;
01082 pr.head = n2;
01083 pr.tail = n2;
01084 return pr;
01085 } else if( pr1.tail->GetOp() != eLIST ) {
01086 CNode* t = cLINK( pr1.head, n2 );
01087 CNode_pr pr;
01088 pr.head = t;
01089 pr.tail = t;
01090 return pr;
01091 } else {
01092 pr1.tail->Arg<CNode*>(1) = cLINK(pr1.tail->Arg<CNode*>(1),n2);
01093 CNode_pr pr;
01094 pr.head = pr1.head;
01095 pr.tail = pr1.tail->Arg<CNode*>(1);
01096 return pr;
01097 }
01098 }
01099
01100
01101
01102
01103 inline CNode* cMAX_N( CNode* first, ... )
01104 {
01105 CNode* result = first;
01106 va_list ap;
01107 va_start( ap, first );
01108 while( 1 ) {
01109 CNode* arg = va_arg(ap,CNode*);
01110 if( !arg ) {
01111 break;
01112 }
01113 result = cMAX( result, arg );
01114 }
01115 va_end( ap );
01116 return result;
01117 }
01118
01119 inline CNode* cADD_N( CNode* first, ... )
01120 {
01121 CNode* result = first;
01122 va_list ap;
01123 va_start( ap, first );
01124 while( 1 ) {
01125 CNode* arg = va_arg(ap,CNode*);
01126 if( !arg ) {
01127 break;
01128 }
01129 result = cADD( result, arg );
01130 }
01131 va_end( ap );
01132 return result;
01133 }
01134
01135 inline CNode* cMUL_N( CNode* first, ... )
01136 {
01137 CNode* result = first;
01138 va_list ap;
01139 va_start( ap, first );
01140 while( 1 ) {
01141 CNode* arg = va_arg(ap,CNode*);
01142 if( !arg ) {
01143 break;
01144 }
01145 result = cMUL( result, arg );
01146 }
01147 va_end( ap );
01148 return result;
01149 }
01150
01151 inline CNode* cABSDIFFPLUS1_N( CNode* first, ... )
01152 {
01153 va_list ap;
01154 va_start( ap, first );
01155 CNode* second = va_arg(ap,CNode*);
01156
01157
01158
01159 MASSERT( va_arg(ap,CNode*) == NULL );
01160 va_end( ap );
01161 return cADD(cABSDIFF(first,second),cINT32(1));
01162 }
01163
01164 inline int cMAX( int a1, int a2 )
01165 {
01166 return a1 < a2 ? a2 : a1;
01167 }
01168
01169 inline int cMAX( int a1, int a2, int a3 )
01170 {
01171 return cMAX(a1,cMAX(a2,a3));
01172 }
01173
01174 inline int cADD( int a1, int a2 )
01175 {
01176 return a1 + a2;
01177 }
01178
01179 inline int cMUL( int a1, int a2 )
01180 {
01181 return a1 * a2;
01182 }
01183
01184 inline int cABSDIFFPLUS1( int a1, int a2 )
01185 {
01186 int diff = a1-a2;
01187 return (diff < 0 ? -diff : diff)+1;
01188 }
01189
01190
01191 #endif // CNODE_HPP
01192