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 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 _LINK( CNode_pr pr1, CNode* n2 );
00149 };
00150
00171 class CNode : public CObject
00172 {
00173 private:
00174 static list<CObstack*> stackList;
00175 static CObstack evalHeap;
00176 static INT32 evalCount;
00177 static CObstack* stack;
00178 static map<CNode*,int> labelCache;
00179 static int labelCacheEnabled;
00180 NodeOp_t op;
00181 void* left;
00182 void* right;
00183 Coord_t loc;
00184 Coord_t *locp;
00185 CNode* attributes;
00186
00187
00188
00189
00190 NodeType_t type;
00191 INT32 width;
00192 int fixedWidth;
00193 private:
00194 int LabelBits( int supressErrorMessages = FALSE );
00195 CNode* FixBits( INT32 newWidth, NodeType_t newType );
00196 void _EvalVector( CVector& v );
00197 double _EvalReal( void );
00198 void FixedWidth( int v ) { fixedWidth = v; }
00199 int FixedWidth() { return fixedWidth; }
00200 int ConditionalWiden();
00201 int WidthFixed();
00202 unsigned NodeMask();
00203 CNode* GetNLeft( void ) { return (CNode*)left; }
00204 CNode* GetNRight( void ) { return (CNode*)right; }
00205 static void _LabelBits( CNode* n, void* arg );
00206 public:
00211 static CObstack* CurrentHeap() { return stack; }
00221 static void UseEvalStack( void ) {
00222 stackList.push_front( stack );
00223 evalCount++;
00224 stack = &evalHeap;
00225 }
00230 static void SetBuildStack( CObstack* aStack ) {
00231 MASSERT( evalCount == 0 );
00232 stackList.push_front( stack );
00233 stack = aStack;
00234 }
00238 static void ResetBuildStack( void ) {
00239 if( stack == &evalHeap ) {
00240 evalCount--;
00241 if( evalCount == 0 ) {
00242 evalHeap.Free( NULL );
00243 }
00244 }
00245 if( stackList.empty() ) {
00246 stack = NULL;
00247 } else {
00248 stack = *stackList.begin();
00249 stackList.pop_front();
00250 }
00251 }
00261 static void EnableLabelCache()
00262 {
00263 labelCacheEnabled = 1;
00264 }
00269 static void DisableAndClearLabelCache()
00270 {
00271 labelCacheEnabled = 0;
00272 labelCache.erase( labelCache.begin(), labelCache.end() );
00273 }
00281 CNode( Coord_t* aLoc, NodeOp_t aOp );
00286 Coord_t* GetCoord() { return locp; }
00291 NodeOp_t GetOp() { return op; }
00298 void SetOp( NodeOp_t aOp ) {
00299 int oldCount = ArgCount();
00300 op = aOp;
00301 MASSERT( oldCount == ArgCount() );
00302 }
00308 unsigned Hash();
00314 template<class T> CNode_sp<T> Arg( int index );
00319 int ArgCount( void );
00325 CNode* Clone( void );
00330 int Precedence();
00337 void PostVisit1( void (*callback)(CNode*,void*), void* data );
00346 CNode* PostSubVisit1( CNode* (*callback)(CNode*,void*),
00347 void* data );
00355 void PreVisit1( int (*callback)(CNode*,void*), void* data );
00364 CNode* Simplify( INT32 newWidth, NodeType_t newType );
00374 int IsNonX( int integerIsNonX = 0, char* exclude = NULL );
00380 int IsConstant();
00390 int IsEvaluateable();
00396 int IsVolatile( void );
00401 INT32 EvalINT32();
00408 void EvalVector( CVector& v );
00417 void EvalVector( CVector& v, INT32 newWidth, NodeType_t newType );
00423 double EvalReal( void );
00428 void Dump( FILE* f );
00434 int IsWidthConstant( void );
00440 int IsWidthVolatile( void );
00450 int IsWidthEvaluateable( void );
00455 CNode* GetWidthExp( void );
00461 INT32 GetWidth( void ) { LabelBits(TRUE); return width; }
00466 int IsScalar( void ) { LabelBits(TRUE); return width==1; }
00471 int IsVector( void ) { LabelBits(TRUE); return width>1; }
00476 int IsReal( void ) { LabelBits(TRUE); return type==eR; }
00481 CNode* GetAttributes() { return attributes; }
00486 void SetAttributes( CNode* attr ) { attributes = attr; }
00491 NodeType_t GetNodeType( void ) { LabelBits(TRUE); return type; }
00492 };
00493
00494
00495
00496
00497
00498
00499
00500 template<class T> CNode_sp<T> CNode::Arg(int index)
00501 {
00502 switch( ArgCount() ) {
00503 case 1:
00504 switch( index ) {
00505 case 0:
00506 return CNode_sp<T>(&left);
00507 default:
00508 MASSERT( FALSE );
00509 return NULL;
00510 }
00511 case 2:
00512 switch( index ) {
00513 case 0:
00514 return CNode_sp<T>(&left);
00515 case 1:
00516 return CNode_sp<T>(&right);
00517 default:
00518 MASSERT( FALSE );
00519 return NULL;
00520 }
00521 case 3:
00522 switch( index ) {
00523 case 0:
00524 return CNode_sp<T>(&GetNLeft()->left);
00525 case 1:
00526 return CNode_sp<T>(&GetNLeft()->right);
00527 case 2:
00528 return CNode_sp<T>(&right);
00529 default:
00530 MASSERT( FALSE );
00531 return NULL;
00532 }
00533 case 4:
00534 switch( index ) {
00535 case 0:
00536 return CNode_sp<T>(&GetNLeft()->left);
00537 case 1:
00538 return CNode_sp<T>(&GetNLeft()->right);
00539 case 2:
00540 return CNode_sp<T>(&GetNRight()->left);
00541 case 3:
00542 return CNode_sp<T>(&GetNRight()->right);
00543 default:
00544 MASSERT( FALSE );
00545 return NULL;
00546 }
00547 case 5:
00548 switch( index ) {
00549 case 0:
00550 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00551 case 1:
00552 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00553 case 2:
00554 return CNode_sp<T>(&GetNLeft()->right);
00555 case 3:
00556 return CNode_sp<T>(&GetNRight()->left);
00557 case 4:
00558 return CNode_sp<T>(&GetNRight()->right);
00559 default:
00560 MASSERT( FALSE );
00561 return NULL;
00562 }
00563 case 6:
00564 switch( index ) {
00565 case 0:
00566 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00567 case 1:
00568 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00569 case 2:
00570 return CNode_sp<T>(&GetNLeft()->GetNRight()->left);
00571 case 3:
00572 return CNode_sp<T>(&GetNLeft()->GetNRight()->right);
00573 case 4:
00574 return CNode_sp<T>(&GetNRight()->left);
00575 case 5:
00576 return CNode_sp<T>(&GetNRight()->right);
00577 default:
00578 MASSERT( FALSE );
00579 return NULL;
00580 }
00581 case 7:
00582 switch( index ) {
00583 case 0:
00584 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00585 case 1:
00586 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00587 case 2:
00588 return CNode_sp<T>(&GetNLeft()->GetNRight()->left);
00589 case 3:
00590 return CNode_sp<T>(&GetNLeft()->GetNRight()->right);
00591 case 4:
00592 return CNode_sp<T>(&GetNRight()->GetNLeft()->left);
00593 case 5:
00594 return CNode_sp<T>(&GetNRight()->GetNLeft()->right);
00595 case 6:
00596 return CNode_sp<T>(&GetNRight()->right);
00597 default:
00598 MASSERT( FALSE );
00599 return NULL;
00600 }
00601 case 8:
00602 switch( index ) {
00603 case 0:
00604 return CNode_sp<T>(&GetNLeft()->GetNLeft()->left);
00605 case 1:
00606 return CNode_sp<T>(&GetNLeft()->GetNLeft()->right);
00607 case 2:
00608 return CNode_sp<T>(&GetNLeft()->GetNRight()->left);
00609 case 3:
00610 return CNode_sp<T>(&GetNLeft()->GetNRight()->right);
00611 case 4:
00612 return CNode_sp<T>(&GetNRight()->GetNLeft()->left);
00613 case 5:
00614 return CNode_sp<T>(&GetNRight()->GetNLeft()->right);
00615 case 6:
00616 return CNode_sp<T>(&GetNRight()->GetNRight()->left);
00617 case 7:
00618 return CNode_sp<T>(&GetNRight()->GetNRight()->right);
00619 default:
00620 MASSERT( FALSE );
00621 return NULL;
00622 }
00623
00624 default:
00625 MASSERT( FALSE );
00626 }
00627 }
00628 int Equivalent( CNode* a, CNode* b );
00629
00630
00631
00632
00633 inline void Add( double* r, double* a, double* b )
00634 {
00635 *r = *a + *b;
00636 }
00637
00638 inline void Sub( double* r, double* a, double* b )
00639 {
00640 *r = *a - *b;
00641 }
00642
00643 inline void Mul( double* r, double* a, double* b )
00644 {
00645 *r = *a * *b;
00646 }
00647
00648 inline void Div( double* r, double* a, double* b )
00649 {
00650 *r = *a / *b;
00651 }
00652
00653 inline void Neg( double* r, double* a )
00654 {
00655 *r = - *a;
00656 }
00657
00658 inline void Pow( double* r, double* a, double* b )
00659 {
00660 *r = pow(*a,*b);
00661 }
00662
00663
00664
00665
00666
00667 #define ILLEGAL_OP2(op) \
00668 inline void op( double*, double*, double* )\
00669 { fatal( NULL, #op " is illegal for reals" ); }
00670
00671 #define ILLEGAL_OP1(op) \
00672 inline void op( double*, double* )\
00673 { fatal( NULL, #op " is illegal for reals" ); }
00674
00675 ILLEGAL_OP2(Rsh);
00676 ILLEGAL_OP2(Lsh);
00677
00678 ILLEGAL_OP2(Rep);
00679 ILLEGAL_OP2(Mod);
00680 ILLEGAL_OP2(And);
00681 ILLEGAL_OP2(Xor);
00682 ILLEGAL_OP2(Xnor);
00683 ILLEGAL_OP2(Or);
00684 ILLEGAL_OP2(Lor);
00685 ILLEGAL_OP2(Land);
00686 ILLEGAL_OP1(Com);
00687 ILLEGAL_OP1(Rand);
00688 ILLEGAL_OP1(Rnand);
00689 ILLEGAL_OP1(Ror);
00690 ILLEGAL_OP1(Rnor);
00691 ILLEGAL_OP1(Rxor);
00692 ILLEGAL_OP1(Rxnor);
00693
00694 #define DEFINE_CONSTRUCTOR
00695 #include "cnode_def.h"
00696 #undef DEFINE_CONSTRUCTOR
00697
00698
00699
00700
00701
00708 inline CNode* _CVECTOR( CVector& vec )
00709 {
00710 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), vec.GetWidth() );
00711 CNode* n;
00712 *v = vec;
00713 v->SetPreferredBase( vec.GetPreferredBase() );
00714 n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00715 n->Arg<CVector*>(0) = v;
00716 return n;
00717 }
00718
00725 inline CNode* _INT32( INT32 i )
00726 {
00727 CVector* v = CVector::AllocFromHeap( CNode::CurrentHeap(), 32 );
00728 CNode* n;
00729 *v = i;
00730 v->Sized(FALSE);
00731 v->Signed(TRUE);
00732 v->Based(FALSE);
00733 n = new(CNode::CurrentHeap()) CNode( NULL, eVCONSTANT );
00734 n->Arg<CVector*>(0) = v;
00735 return n;
00736 }
00737
00744 inline CNode* _REAL( double number )
00745 {
00746 CNode* node = new(CNode::CurrentHeap()) CNode( NULL, eRCONSTANT );
00747 node->Arg<char*>(0) = d2s(number,CNode::CurrentHeap());
00748 return node;
00749 }
00750
00758 inline CNode* _ELINK( CNode* n1, CNode* n2 )
00759 {
00760 if( n1 == NULL ) {
00761 return n2;
00762 } else if( n2 == NULL ) {
00763 return n1;
00764 }
00765 return _ELIST( n1, n2 );
00766 }
00767
00775 inline CNode* _ABS( CNode* a )
00776 {
00777 CNode* a1 = a->Clone();
00778 CNode* a2 = a->Clone();
00779 CNode* c = _GE(a,_INT32(0));
00780 return _HOOK( c, a1, _NEG( a2) );
00781 }
00782
00791 inline CNode* _ABSDIFF( CNode* a, CNode* b )
00792 {
00793 return _ABS( _SUB( a, b ) );
00794 }
00795
00804 inline CNode* _LINK( CNode* n1, CNode* n2 )
00805 {
00806 if( n1 == NULL ) {
00807 return n2;
00808 } else if( n2 == NULL ) {
00809 return n1;
00810 }
00811 return _LIST( n1, n2 );
00812 }
00813
00822 inline CNode* _MAX( CNode* n1, CNode* n2 )
00823 {
00824 CNode* cond = _LT(n2->Clone(),n1->Clone());
00825 return _HOOK(cond,n1,n2);
00826 }
00827
00828
00829
00830
00831
00832
00845 template<class T> void ArgList2Vector(CNode* n, NodeOp_t op,
00846 int argNumber, vector<T>& v)
00847 {
00848 if( !n ) {
00849 return;
00850 }
00851 switch( n->GetOp() ) {
00852 case eLIST:
00853 ArgList2Vector<T>(n->Arg<CNode*>(0),op,argNumber,v);
00854 ArgList2Vector<T>(n->Arg<CNode*>(1),op,argNumber,v);
00855 break;
00856 default:
00857 if( n->GetOp() == op ) {
00858 v.push_back(n->Arg<T>(argNumber));
00859 }
00860 break;
00861 }
00862 }
00863
00872 inline void EList2VectorExclude(CNode* n, const set<NodeOp_t>& excludeOps, vector<CNode*>& v)
00873 {
00874 if( !n ) {
00875 return;
00876 }
00877 switch( n->GetOp() ) {
00878 case eELIST:
00879 EList2VectorExclude(n->Arg<CNode*>(0),excludeOps,v);
00880 EList2VectorExclude(n->Arg<CNode*>(1),excludeOps,v);
00881 break;
00882 default:
00883 if( excludeOps.find(n->GetOp()) == excludeOps.end() ) {
00884 v.push_back(n);
00885 }
00886 break;
00887 }
00888 }
00889
00896 inline CNode* Vector2EList(vector<CNode*>& v)
00897 {
00898 CNode* result = NULL;
00899 vector<CNode*>::reverse_iterator ptr;
00900 for( ptr = v.rbegin(); ptr != v.rend(); ++ptr ) {
00901 if( result ) {
00902 result = _ELIST(*ptr, result);
00903 } else {
00904 result = *ptr;
00905 }
00906 }
00907 return result;
00908 }
00909
00918 inline int ListCount(CNode* n, NodeOp_t op)
00919 {
00920 int result = 0;
00921 if( !n ) {
00922 return result;
00923 }
00924 switch( n->GetOp() ) {
00925 case eLIST:
00926 case eELIST:
00927 result += ListCount(n->Arg<CNode*>(0),op);
00928 result += ListCount(n->Arg<CNode*>(1),op);
00929 break;
00930 default:
00931 if( n->GetOp() == op ) {
00932 result = 1;
00933 }
00934 break;
00935 }
00936 return result;
00937 }
00938
00945 inline int ListCount(CNode* n)
00946 {
00947 int result = 0;
00948 if( !n ) {
00949 return result;
00950 }
00951 switch( n->GetOp() ) {
00952 case eLIST:
00953 case eELIST:
00954 result += ListCount(n->Arg<CNode*>(0));
00955 result += ListCount(n->Arg<CNode*>(1));
00956 break;
00957 default:
00958 result = 1;
00959 break;
00960 }
00961 return result;
00962 }
00963
00974 inline double s2d( char* s ) {
00975 return atof(s);
00976 }
00977
00986 inline char* d2s( double d, CObstack* heap ) {
00987 char buffer[256];
00988
00989
00990 snprintf( buffer, sizeof(buffer), "%g", d );
00991 char* s = (char*)heap->Alloc(strlen(buffer)+1);
00992 strcpy( s, buffer );
00993 return s;
00994 }
00995
00996
00997
00998
00999
01000 inline CNode* RebalanceRight( CNode* n ) {
01001 if( n == NULL ) {
01002 return n;
01003 }
01004 if( n->GetOp() != eLIST ) {
01005 return n;
01006 }
01007 CNode* result = n;
01008 CNode* parent = NULL;
01009 while( 1 ) {
01010 while( n->Arg<CNode*>(0) && n->Arg<CNode*>(0)->GetOp() == eLIST ) {
01011 CNode* l = n->Arg<CNode*>(0);
01012 CNode* ll = l->Arg<CNode*>(0);
01013 CNode* lr = l->Arg<CNode*>(1);
01014 l->Arg<CNode*>(1) = n;
01015 n->Arg<CNode*>(0) = lr;
01016 n = l;
01017 if( parent ) {
01018 parent->Arg<CNode*>(1) = n;
01019 } else {
01020 result = n;
01021 }
01022 }
01023 if( n->Arg<CNode*>(1) && n->Arg<CNode*>(1)->GetOp() == eLIST ) {
01024 parent = n;
01025 n = n->Arg<CNode*>(1);
01026 } else {
01027 break;
01028 }
01029 }
01030 return result;
01031 }
01032
01033
01034
01035
01036
01037
01038 inline void MeasureDepth( CNode* n, int* count, int* depth )
01039 {
01040 *count = 0;
01041 *depth = 0;
01042 if( !n ) {
01043 return;
01044 }
01045 if( n->GetOp() == eLIST ) {
01046 int count0 = 0;
01047 int depth0 = 0;
01048 int count1 = 0;
01049 int depth1 = 0;
01050 if( n->Arg<CNode*>(0) ) {
01051 MeasureDepth( n->Arg<CNode*>(0), &count0, &depth0 );
01052 depth0++;
01053 }
01054 if( n->Arg<CNode*>(1) ) {
01055 MeasureDepth( n->Arg<CNode*>(1), &count1, &depth1 );
01056 }
01057 *count = count0+count1;
01058 *depth = depth0 > depth1 ? depth0 : depth1;
01059 }
01060 (*count)++;
01061 }
01062
01063
01064
01065
01066
01067
01068 inline CNode_pr _LINK( CNode_pr pr1, CNode* n2 )
01069 {
01070 if( !n2 ) {
01071 return pr1;
01072 } else if( !pr1.tail ) {
01073 CNode_pr pr;
01074 pr.head = n2;
01075 pr.tail = n2;
01076 return pr;
01077 } else if( pr1.tail->GetOp() != eLIST ) {
01078 CNode* t = _LINK( pr1.head, n2 );
01079 CNode_pr pr;
01080 pr.head = t;
01081 pr.tail = t;
01082 return pr;
01083 } else {
01084 pr1.tail->Arg<CNode*>(1) = _LINK(pr1.tail->Arg<CNode*>(1),n2);
01085 CNode_pr pr;
01086 pr.head = pr1.head;
01087 pr.tail = pr1.tail->Arg<CNode*>(1);
01088 return pr;
01089 }
01090 }
01091
01092
01093
01094
01095 inline CNode* _MAX_N( CNode* first, ... )
01096 {
01097 CNode* result = first;
01098 va_list ap;
01099 va_start( ap, first );
01100 while( 1 ) {
01101 CNode* arg = va_arg(ap,CNode*);
01102 if( !arg ) {
01103 break;
01104 }
01105 result = _MAX( result, arg );
01106 }
01107 va_end( ap );
01108 return result;
01109 }
01110
01111 inline CNode* _ADD_N( CNode* first, ... )
01112 {
01113 CNode* result = first;
01114 va_list ap;
01115 va_start( ap, first );
01116 while( 1 ) {
01117 CNode* arg = va_arg(ap,CNode*);
01118 if( !arg ) {
01119 break;
01120 }
01121 result = _ADD( result, arg );
01122 }
01123 va_end( ap );
01124 return result;
01125 }
01126
01127 inline CNode* _MUL_N( CNode* first, ... )
01128 {
01129 CNode* result = first;
01130 va_list ap;
01131 va_start( ap, first );
01132 while( 1 ) {
01133 CNode* arg = va_arg(ap,CNode*);
01134 if( !arg ) {
01135 break;
01136 }
01137 result = _MUL( result, arg );
01138 }
01139 va_end( ap );
01140 return result;
01141 }
01142
01143 inline CNode* _ABSDIFFPLUS1_N( CNode* first, ... )
01144 {
01145 va_list ap;
01146 va_start( ap, first );
01147 CNode* second = va_arg(ap,CNode*);
01148
01149
01150
01151 MASSERT( va_arg(ap,CNode*) == NULL );
01152 va_end( ap );
01153 return _ADD(_ABSDIFF(first,second),_INT32(1));
01154 }
01155
01156 inline int _MAX( int a1, int a2 )
01157 {
01158 return a1 < a2 ? a2 : a1;
01159 }
01160
01161 inline int _MAX( int a1, int a2, int a3 )
01162 {
01163 return _MAX(a1,_MAX(a2,a3));
01164 }
01165
01166 inline int _ADD( int a1, int a2 )
01167 {
01168 return a1 + a2;
01169 }
01170
01171 inline int _MUL( int a1, int a2 )
01172 {
01173 return a1 * a2;
01174 }
01175
01176 inline int _ABSDIFFPLUS1( int a1, int a2 )
01177 {
01178 int diff = a1-a2;
01179 return (diff < 0 ? -diff : diff)+1;
01180 }
01181
01182
01183 #endif // CNODE_HPP
01184