1 /**CFile****************************************************************
2
3 FileName [dchClass.c]
4
5 SystemName [ABC: Logic synthesis and verification system.]
6
7 PackageName [Choice computation for tech-mapping.]
8
9 Synopsis [Representation of candidate equivalence classes.]
10
11 Author [Alan Mishchenko]
12
13 Affiliation [UC Berkeley]
14
15 Date [Ver. 1.0. Started - June 29, 2008.]
16
17 Revision [$Id: dchClass.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
18
19 ***********************************************************************/
20
21 #include "dchInt.h"
22
23 ABC_NAMESPACE_IMPL_START
24
25
26 /*
27 The candidate equivalence classes are stored as a vector of pointers
28 to the array of pointers to the nodes in each class.
29 The first node of the class is its representative node.
30 The representative has the smallest topological order among the class nodes.
31 The nodes inside each class are ordered according to their topological order.
32 The classes are ordered according to the topo order of their representatives.
33 */
34
35 // internal representation of candidate equivalence classes
36 struct Dch_Cla_t_
37 {
38 // class information
39 Aig_Man_t * pAig; // original AIG manager
40 Aig_Obj_t *** pId2Class; // non-const classes by ID of repr node
41 int * pClassSizes; // sizes of each equivalence class
42 // statistics
43 int nClasses; // the total number of non-const classes
44 int nCands1; // the total number of const candidates
45 int nLits; // the number of literals in all classes
46 // memory
47 Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes
48 Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used
49 // temporary data
50 Vec_Ptr_t * vClassOld; // old equivalence class after splitting
51 Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting
52 // procedures used for class refinement
53 void * pManData;
54 unsigned (*pFuncNodeHash) (void *,Aig_Obj_t *); // returns hash key of the node
55 int (*pFuncNodeIsConst) (void *,Aig_Obj_t *); // returns 1 if the node is a constant
56 int (*pFuncNodesAreEqual) (void *,Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement
57 };
58
59 ////////////////////////////////////////////////////////////////////////
60 /// DECLARATIONS ///
61 ////////////////////////////////////////////////////////////////////////
62
Dch_ObjNext(Aig_Obj_t ** ppNexts,Aig_Obj_t * pObj)63 static inline Aig_Obj_t * Dch_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; }
Dch_ObjSetNext(Aig_Obj_t ** ppNexts,Aig_Obj_t * pObj,Aig_Obj_t * pNext)64 static inline void Dch_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; }
65
66 // iterator through the equivalence classes
67 #define Dch_ManForEachClass( p, ppClass, i ) \
68 for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) \
69 if ( ((ppClass) = p->pId2Class[i]) == NULL ) {} else
70 // iterator through the nodes in one class
71 #define Dch_ClassForEachNode( p, pRepr, pNode, i ) \
72 for ( i = 0; i < p->pClassSizes[pRepr->Id]; i++ ) \
73 if ( ((pNode) = p->pId2Class[pRepr->Id][i]) == NULL ) {} else
74
75 ////////////////////////////////////////////////////////////////////////
76 /// FUNCTION DEFINITIONS ///
77 ////////////////////////////////////////////////////////////////////////
78
79 /**Function*************************************************************
80
81 Synopsis [Creates one equivalence class.]
82
83 Description []
84
85 SideEffects []
86
87 SeeAlso []
88
89 ***********************************************************************/
Dch_ObjAddClass(Dch_Cla_t * p,Aig_Obj_t * pRepr,Aig_Obj_t ** pClass,int nSize)90 static inline void Dch_ObjAddClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Aig_Obj_t ** pClass, int nSize )
91 {
92 assert( p->pId2Class[pRepr->Id] == NULL );
93 p->pId2Class[pRepr->Id] = pClass;
94 assert( p->pClassSizes[pRepr->Id] == 0 );
95 assert( nSize > 1 );
96 p->pClassSizes[pRepr->Id] = nSize;
97 p->nClasses++;
98 p->nLits += nSize - 1;
99 }
100
101 /**Function*************************************************************
102
103 Synopsis [Removes one equivalence class.]
104
105 Description []
106
107 SideEffects []
108
109 SeeAlso []
110
111 ***********************************************************************/
Dch_ObjRemoveClass(Dch_Cla_t * p,Aig_Obj_t * pRepr)112 static inline Aig_Obj_t ** Dch_ObjRemoveClass( Dch_Cla_t * p, Aig_Obj_t * pRepr )
113 {
114 Aig_Obj_t ** pClass = p->pId2Class[pRepr->Id];
115 int nSize;
116 assert( pClass != NULL );
117 p->pId2Class[pRepr->Id] = NULL;
118 nSize = p->pClassSizes[pRepr->Id];
119 assert( nSize > 1 );
120 p->nClasses--;
121 p->nLits -= nSize - 1;
122 p->pClassSizes[pRepr->Id] = 0;
123 return pClass;
124 }
125
126 /**Function*************************************************************
127
128 Synopsis [Starts representation of equivalence classes.]
129
130 Description []
131
132 SideEffects []
133
134 SeeAlso []
135
136 ***********************************************************************/
Dch_ClassesStart(Aig_Man_t * pAig)137 Dch_Cla_t * Dch_ClassesStart( Aig_Man_t * pAig )
138 {
139 Dch_Cla_t * p;
140 p = ABC_ALLOC( Dch_Cla_t, 1 );
141 memset( p, 0, sizeof(Dch_Cla_t) );
142 p->pAig = pAig;
143 p->pId2Class = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) );
144 p->pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
145 p->vClassOld = Vec_PtrAlloc( 100 );
146 p->vClassNew = Vec_PtrAlloc( 100 );
147 assert( pAig->pReprs == NULL );
148 Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
149 return p;
150 }
151
152 /**Function*************************************************************
153
154 Synopsis [Starts representation of equivalence classes.]
155
156 Description []
157
158 SideEffects []
159
160 SeeAlso []
161
162 ***********************************************************************/
Dch_ClassesSetData(Dch_Cla_t * p,void * pManData,unsigned (* pFuncNodeHash)(void *,Aig_Obj_t *),int (* pFuncNodeIsConst)(void *,Aig_Obj_t *),int (* pFuncNodesAreEqual)(void *,Aig_Obj_t *,Aig_Obj_t *))163 void Dch_ClassesSetData( Dch_Cla_t * p, void * pManData,
164 unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), // returns hash key of the node
165 int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), // returns 1 if the node is a constant
166 int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ) // returns 1 if nodes are equal up to a complement
167 {
168 p->pManData = pManData;
169 p->pFuncNodeHash = pFuncNodeHash;
170 p->pFuncNodeIsConst = pFuncNodeIsConst;
171 p->pFuncNodesAreEqual = pFuncNodesAreEqual;
172 }
173
174 /**Function*************************************************************
175
176 Synopsis [Stop representation of equivalence classes.]
177
178 Description []
179
180 SideEffects []
181
182 SeeAlso []
183
184 ***********************************************************************/
Dch_ClassesStop(Dch_Cla_t * p)185 void Dch_ClassesStop( Dch_Cla_t * p )
186 {
187 if ( p->vClassNew ) Vec_PtrFree( p->vClassNew );
188 if ( p->vClassOld ) Vec_PtrFree( p->vClassOld );
189 ABC_FREE( p->pId2Class );
190 ABC_FREE( p->pClassSizes );
191 ABC_FREE( p->pMemClasses );
192 ABC_FREE( p );
193 }
194
195 /**Function*************************************************************
196
197 Synopsis [Stop representation of equivalence classes.]
198
199 Description []
200
201 SideEffects []
202
203 SeeAlso []
204
205 ***********************************************************************/
Dch_ClassesLitNum(Dch_Cla_t * p)206 int Dch_ClassesLitNum( Dch_Cla_t * p )
207 {
208 return p->nLits;
209 }
210
211 /**Function*************************************************************
212
213 Synopsis [Stop representation of equivalence classes.]
214
215 Description []
216
217 SideEffects []
218
219 SeeAlso []
220
221 ***********************************************************************/
Dch_ClassesReadClass(Dch_Cla_t * p,Aig_Obj_t * pRepr,int * pnSize)222 Aig_Obj_t ** Dch_ClassesReadClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize )
223 {
224 assert( p->pId2Class[pRepr->Id] != NULL );
225 assert( p->pClassSizes[pRepr->Id] > 1 );
226 *pnSize = p->pClassSizes[pRepr->Id];
227 return p->pId2Class[pRepr->Id];
228 }
229
230 /**Function*************************************************************
231
232 Synopsis [Checks candidate equivalence classes.]
233
234 Description []
235
236 SideEffects []
237
238 SeeAlso []
239
240 ***********************************************************************/
Dch_ClassesCheck(Dch_Cla_t * p)241 void Dch_ClassesCheck( Dch_Cla_t * p )
242 {
243 Aig_Obj_t * pObj, * pPrev, ** ppClass;
244 int i, k, nLits, nClasses, nCands1;
245 nClasses = nLits = 0;
246 Dch_ManForEachClass( p, ppClass, k )
247 {
248 pPrev = NULL;
249 Dch_ClassForEachNode( p, ppClass[0], pObj, i )
250 {
251 if ( i == 0 )
252 assert( Aig_ObjRepr(p->pAig, pObj) == NULL );
253 else
254 {
255 assert( Aig_ObjRepr(p->pAig, pObj) == ppClass[0] );
256 assert( pPrev->Id < pObj->Id );
257 nLits++;
258 }
259 pPrev = pObj;
260 }
261 nClasses++;
262 }
263 nCands1 = 0;
264 Aig_ManForEachObj( p->pAig, pObj, i )
265 nCands1 += Dch_ObjIsConst1Cand( p->pAig, pObj );
266 assert( p->nLits == nLits );
267 assert( p->nCands1 == nCands1 );
268 assert( p->nClasses == nClasses );
269 }
270
271 /**Function*************************************************************
272
273 Synopsis [Prints simulation classes.]
274
275 Description []
276
277 SideEffects []
278
279 SeeAlso []
280
281 ***********************************************************************/
Dch_ClassesPrintOne(Dch_Cla_t * p,Aig_Obj_t * pRepr)282 void Dch_ClassesPrintOne( Dch_Cla_t * p, Aig_Obj_t * pRepr )
283 {
284 Aig_Obj_t * pObj;
285 int i;
286 Abc_Print( 1, "{ " );
287 Dch_ClassForEachNode( p, pRepr, pObj, i )
288 Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) );
289 Abc_Print( 1, "}\n" );
290 }
291
292 /**Function*************************************************************
293
294 Synopsis [Prints simulation classes.]
295
296 Description []
297
298 SideEffects []
299
300 SeeAlso []
301
302 ***********************************************************************/
Dch_ClassesPrint(Dch_Cla_t * p,int fVeryVerbose)303 void Dch_ClassesPrint( Dch_Cla_t * p, int fVeryVerbose )
304 {
305 Aig_Obj_t ** ppClass;
306 Aig_Obj_t * pObj;
307 int i;
308 Abc_Print( 1, "Equivalence classes: Const1 = %5d. Class = %5d. Lit = %5d.\n",
309 p->nCands1, p->nClasses, p->nLits );
310 if ( !fVeryVerbose )
311 return;
312 Abc_Print( 1, "Constants { " );
313 Aig_ManForEachObj( p->pAig, pObj, i )
314 if ( Dch_ObjIsConst1Cand( p->pAig, pObj ) )
315 Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) );
316 Abc_Print( 1, "}\n" );
317 Dch_ManForEachClass( p, ppClass, i )
318 {
319 Abc_Print( 1, "%3d (%3d) : ", i, p->pClassSizes[i] );
320 Dch_ClassesPrintOne( p, ppClass[0] );
321 }
322 Abc_Print( 1, "\n" );
323 }
324
325 /**Function*************************************************************
326
327 Synopsis [Creates initial simulation classes.]
328
329 Description [Assumes that simulation info is assigned.]
330
331 SideEffects []
332
333 SeeAlso []
334
335 ***********************************************************************/
Dch_ClassesPrepare(Dch_Cla_t * p,int fLatchCorr,int nMaxLevs)336 void Dch_ClassesPrepare( Dch_Cla_t * p, int fLatchCorr, int nMaxLevs )
337 {
338 Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew;
339 Aig_Obj_t * pObj, * pTemp, * pRepr;
340 int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2;
341
342 // allocate the hash table hashing simulation info into nodes
343 nTableSize = Abc_PrimeCudd( Aig_ManObjNumMax(p->pAig)/4 );
344 ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize );
345 ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) );
346
347 // add all the nodes to the hash table
348 nEntries = 0;
349 Aig_ManForEachObj( p->pAig, pObj, i )
350 {
351 if ( fLatchCorr )
352 {
353 if ( !Aig_ObjIsCi(pObj) )
354 continue;
355 }
356 else
357 {
358 if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
359 continue;
360 // skip the node with more that the given number of levels
361 if ( nMaxLevs && (int)pObj->Level >= nMaxLevs )
362 continue;
363 }
364 // check if the node belongs to the class of constant 1
365 if ( p->pFuncNodeIsConst( p->pManData, pObj ) )
366 {
367 Dch_ObjSetConst1Cand( p->pAig, pObj );
368 p->nCands1++;
369 continue;
370 }
371 // hash the node by its simulation info
372 iEntry = p->pFuncNodeHash( p->pManData, pObj ) % nTableSize;
373 // add the node to the class
374 if ( ppTable[iEntry] == NULL )
375 ppTable[iEntry] = pObj;
376 else
377 {
378 // set the representative of this node
379 pRepr = ppTable[iEntry];
380 Aig_ObjSetRepr( p->pAig, pObj, pRepr );
381 // add node to the table
382 if ( Dch_ObjNext( ppNexts, pRepr ) == NULL )
383 { // this will be the second entry
384 p->pClassSizes[pRepr->Id]++;
385 nEntries++;
386 }
387 // add the entry to the list
388 Dch_ObjSetNext( ppNexts, pObj, Dch_ObjNext( ppNexts, pRepr ) );
389 Dch_ObjSetNext( ppNexts, pRepr, pObj );
390 p->pClassSizes[pRepr->Id]++;
391 nEntries++;
392 }
393 }
394
395 // allocate room for classes
396 p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, nEntries + p->nCands1 );
397 p->pMemClassesFree = p->pMemClasses + nEntries;
398
399 // copy the entries into storage in the topological order
400 nEntries2 = 0;
401 Aig_ManForEachObj( p->pAig, pObj, i )
402 {
403 if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
404 continue;
405 nNodes = p->pClassSizes[pObj->Id];
406 // skip the nodes that are not representatives of non-trivial classes
407 if ( nNodes == 0 )
408 continue;
409 assert( nNodes > 1 );
410 // add the nodes to the class in the topological order
411 ppClassNew = p->pMemClasses + nEntries2;
412 ppClassNew[0] = pObj;
413 for ( pTemp = Dch_ObjNext(ppNexts, pObj), k = 1; pTemp;
414 pTemp = Dch_ObjNext(ppNexts, pTemp), k++ )
415 {
416 ppClassNew[nNodes-k] = pTemp;
417 }
418 // add the class of nodes
419 p->pClassSizes[pObj->Id] = 0;
420 Dch_ObjAddClass( p, pObj, ppClassNew, nNodes );
421 // increment the number of entries
422 nEntries2 += nNodes;
423 }
424 assert( nEntries == nEntries2 );
425 ABC_FREE( ppTable );
426 ABC_FREE( ppNexts );
427 // now it is time to refine the classes
428 Dch_ClassesRefine( p );
429 Dch_ClassesCheck( p );
430 }
431
432 /**Function*************************************************************
433
434 Synopsis [Iteratively refines the classes after simulation.]
435
436 Description [Returns the number of refinements performed.]
437
438 SideEffects []
439
440 SeeAlso []
441
442 ***********************************************************************/
Dch_ClassesRefineOneClass(Dch_Cla_t * p,Aig_Obj_t * pReprOld,int fRecursive)443 int Dch_ClassesRefineOneClass( Dch_Cla_t * p, Aig_Obj_t * pReprOld, int fRecursive )
444 {
445 Aig_Obj_t ** pClassOld, ** pClassNew;
446 Aig_Obj_t * pObj, * pReprNew;
447 int i;
448
449 // split the class
450 Vec_PtrClear( p->vClassOld );
451 Vec_PtrClear( p->vClassNew );
452 Dch_ClassForEachNode( p, pReprOld, pObj, i )
453 if ( p->pFuncNodesAreEqual(p->pManData, pReprOld, pObj) )
454 Vec_PtrPush( p->vClassOld, pObj );
455 else
456 Vec_PtrPush( p->vClassNew, pObj );
457 // check if splitting happened
458 if ( Vec_PtrSize(p->vClassNew) == 0 )
459 return 0;
460
461 // get the new representative
462 pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
463 assert( Vec_PtrSize(p->vClassOld) > 0 );
464 assert( Vec_PtrSize(p->vClassNew) > 0 );
465
466 // create old class
467 pClassOld = Dch_ObjRemoveClass( p, pReprOld );
468 Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i )
469 {
470 pClassOld[i] = pObj;
471 Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL );
472 }
473 // create new class
474 pClassNew = pClassOld + i;
475 Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
476 {
477 pClassNew[i] = pObj;
478 Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
479 }
480
481 // put classes back
482 if ( Vec_PtrSize(p->vClassOld) > 1 )
483 Dch_ObjAddClass( p, pReprOld, pClassOld, Vec_PtrSize(p->vClassOld) );
484 if ( Vec_PtrSize(p->vClassNew) > 1 )
485 Dch_ObjAddClass( p, pReprNew, pClassNew, Vec_PtrSize(p->vClassNew) );
486
487 // check if the class should be recursively refined
488 if ( fRecursive && Vec_PtrSize(p->vClassNew) > 1 )
489 return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 );
490 return 1;
491 }
492
493 /**Function*************************************************************
494
495 Synopsis [Refines the classes after simulation.]
496
497 Description []
498
499 SideEffects []
500
501 SeeAlso []
502
503 ***********************************************************************/
Dch_ClassesRefine(Dch_Cla_t * p)504 int Dch_ClassesRefine( Dch_Cla_t * p )
505 {
506 Aig_Obj_t ** ppClass;
507 int i, nRefis = 0;
508 Dch_ManForEachClass( p, ppClass, i )
509 nRefis += Dch_ClassesRefineOneClass( p, ppClass[0], 0 );
510 return nRefis;
511 }
512
513
514 /**Function*************************************************************
515
516 Synopsis [Returns equivalence class of the given node.]
517
518 Description []
519
520 SideEffects []
521
522 SeeAlso []
523
524 ***********************************************************************/
Dch_ClassesCollectOneClass(Dch_Cla_t * p,Aig_Obj_t * pRepr,Vec_Ptr_t * vRoots)525 void Dch_ClassesCollectOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vRoots )
526 {
527 Aig_Obj_t * pObj;
528 int i;
529 Vec_PtrClear( vRoots );
530 Dch_ClassForEachNode( p, pRepr, pObj, i )
531 Vec_PtrPush( vRoots, pObj );
532 assert( Vec_PtrSize(vRoots) > 1 );
533 }
534
535 /**Function*************************************************************
536
537 Synopsis [Returns equivalence class of the given node.]
538
539 Description []
540
541 SideEffects []
542
543 SeeAlso []
544
545 ***********************************************************************/
Dch_ClassesCollectConst1Group(Dch_Cla_t * p,Aig_Obj_t * pObj,int nNodes,Vec_Ptr_t * vRoots)546 void Dch_ClassesCollectConst1Group( Dch_Cla_t * p, Aig_Obj_t * pObj, int nNodes, Vec_Ptr_t * vRoots )
547 {
548 int i, Limit;
549 Vec_PtrClear( vRoots );
550 Limit = Abc_MinInt( pObj->Id + nNodes, Aig_ManObjNumMax(p->pAig) );
551 for ( i = pObj->Id; i < Limit; i++ )
552 {
553 pObj = Aig_ManObj( p->pAig, i );
554 if ( pObj && Dch_ObjIsConst1Cand( p->pAig, pObj ) )
555 Vec_PtrPush( vRoots, pObj );
556 }
557 }
558
559 /**Function*************************************************************
560
561 Synopsis [Refine the group of constant 1 nodes.]
562
563 Description []
564
565 SideEffects []
566
567 SeeAlso []
568
569 ***********************************************************************/
Dch_ClassesRefineConst1Group(Dch_Cla_t * p,Vec_Ptr_t * vRoots,int fRecursive)570 int Dch_ClassesRefineConst1Group( Dch_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive )
571 {
572 Aig_Obj_t * pObj, * pReprNew, ** ppClassNew;
573 int i;
574 if ( Vec_PtrSize(vRoots) == 0 )
575 return 0;
576 // collect the nodes to be refined
577 Vec_PtrClear( p->vClassNew );
578 Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i )
579 if ( !p->pFuncNodeIsConst( p->pManData, pObj ) )
580 Vec_PtrPush( p->vClassNew, pObj );
581 // check if there is a new class
582 if ( Vec_PtrSize(p->vClassNew) == 0 )
583 return 0;
584 p->nCands1 -= Vec_PtrSize(p->vClassNew);
585 pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
586 Aig_ObjSetRepr( p->pAig, pReprNew, NULL );
587 if ( Vec_PtrSize(p->vClassNew) == 1 )
588 return 1;
589 // create a new class composed of these nodes
590 ppClassNew = p->pMemClassesFree;
591 p->pMemClassesFree += Vec_PtrSize(p->vClassNew);
592 Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
593 {
594 ppClassNew[i] = pObj;
595 Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
596 }
597 Dch_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) );
598 // refine them recursively
599 if ( fRecursive )
600 return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 );
601 return 1;
602 }
603
604
605 ////////////////////////////////////////////////////////////////////////
606 /// END OF FILE ///
607 ////////////////////////////////////////////////////////////////////////
608
609
610 ABC_NAMESPACE_IMPL_END
611
612