extraUtilPrime.c 21.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/**CFile****************************************************************

  FileName    [extraUtilPrime.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [extra]

  Synopsis    [Function enumeration.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - June 20, 2005.]

  Revision    [$Id: extraUtilPrime.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]

***********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "misc/vec/vec.h"
#include "misc/vec/vecHsh.h"
#include "bool/kit/kit.h"
28
#include "misc/extra/extra.h"
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

ABC_NAMESPACE_IMPL_START

////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_GenCountDump( Vec_Int_t * vPrimes, int nVars, char * pFileName )
{
    FILE * pFile;
    int i, k, Prime;
    pFile = fopen( pFileName, "wb" );
    fprintf( pFile, "# %d prime numbers up to 2^%d generated by ABC on %s\n", Vec_IntSize(vPrimes), nVars, Extra_TimeStamp() );
    fprintf( pFile, ".i %d\n", nVars );
    fprintf( pFile, ".o %d\n", 1 );
    fprintf( pFile, ".p %d\n", Vec_IntSize(vPrimes) );
    Vec_IntForEachEntry( vPrimes, Prime, i )
        for ( k = nVars-1; k >= 0; k-- )
            fprintf( pFile, "%d%s", (Prime >> k)&1, k ? "" : " 1\n" );
    fprintf( pFile, ".e\n\n" );
    fclose( pFile );
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_GenCountHits1( Vec_Bit_t * vMap, Vec_Int_t * vPrimes, int nVars )
{
    abctime clk = Abc_Clock();
    int i, k, Prime, Count = 0;
    Vec_IntForEachEntry( vPrimes, Prime, i )
    {
        for ( k = 0; k < nVars; k++ )
            if ( !Vec_BitEntry(vMap, Prime ^ (1<<k)) )
86 87
            {
                //printf( "%3d : %2d %2d     flipped bit %d\n", Count, Prime, Prime ^ (1<<k), k );
88
                Count++;
89
            }
90
    }
91
    printf( "Dist1 pairs = %d. ", Count/2 );
92 93 94 95 96 97 98
    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
Vec_Int_t * Abc_GenPrimes( int nVars )
{
    int i, n, nBits = ( 1 << nVars );
    Vec_Bit_t * vMap = Vec_BitStart( nBits );
    Vec_Int_t * vPrimes = Vec_IntAlloc( 1000 );
99 100
    Vec_BitWriteEntry(vMap, 0, 1);
    Vec_BitWriteEntry(vMap, 1, 1);
101 102 103 104 105 106 107
    for ( n = 2; n < nBits; n++ )
        if ( !Vec_BitEntry(vMap, n) )
            for ( i = 2*n; i < nBits; i += n )
                Vec_BitWriteEntry(vMap, i, 1);
    for ( n = 2; n < nBits; n++ )
        if ( !Vec_BitEntry(vMap, n) )
            Vec_IntPush( vPrimes, n );
108
    printf( "Primes up to 2^%d = %d\n", nVars, Vec_IntSize(vPrimes) );
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
    Abc_GenCountHits1( vMap, vPrimes, nVars );
    Vec_BitFree( vMap );
    return vPrimes;
}
void Abc_GenPrimesTest()
{
    // 54,400,028 primes up to 2^30 can be computed in 22 sec
    int nVars = 18;
    Vec_Int_t * vPrimes = Abc_GenPrimes( nVars );
    Abc_GenCountDump( vPrimes, nVars, "primes18.pla" );
    //Vec_IntPrint( vPrimes );
    printf( "Primes up to 2^%d = %d\n", nVars, Vec_IntSize(vPrimes) );

    Vec_IntFree( vPrimes );
}

125 126


127 128 129

#define ABC_PRIME_MASK 0xFF
static unsigned s_256Primes[ABC_PRIME_MASK+1] = 
130
{
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
    0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55,
    0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055,
    0x50d66b74,0x2f01ae9e,0xa1a80123,0x3e1ce2dc,0xebedbc57,0x4e68bc34,0x855ee0cf,0x17275120,
    0x2ae7f2df,0xf71039eb,0x7c283eec,0x70cd1137,0x7cf651f3,0xa87bfa7a,0x14d87f02,0xe82e197d,
    0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035,
    0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10,
    0x8fa783f7,0x252062ce,0x3dc46b4b,0xf70f6432,0x3f378276,0x44b137a1,0x2bf74b77,0x04892ed6,
    0xfd318de1,0xd58c235e,0x94c6d25b,0x7aa5f218,0x35c9e921,0x5732fbbb,0x06026481,0xf584a44f,
    0x946e1b5f,0x8463d5b2,0x4ebca7b2,0x54887b15,0x08d1e804,0x5b22067d,0x794580f6,0xb351ea43,
    0xbce555b9,0x19ae2194,0xd32f1396,0x6fc1a7f1,0x1fd8a867,0x3a89fdb0,0xea49c61c,0x25f8a879,
    0xde1e6437,0x7c74afca,0x8ba63e50,0xb1572074,0xe4655092,0xdb6f8b1c,0xc2955f3c,0x327f85ba,
    0x60a17021,0x95bd261d,0xdea94f28,0x04528b65,0xbe0109cc,0x26dd5688,0x6ab2729d,0xc4f029ce,
    0xacf7a0be,0x4c912f55,0x34c06e65,0x4fbb938e,0x1533fb5f,0x03da06bd,0x48262889,0xc2523d7d,
    0x28a71d57,0x89f9713a,0xf574c551,0x7a99deb5,0x52834d91,0x5a6f4484,0xc67ba946,0x13ae698f,
    0x3e390f34,0x34fc9593,0x894c7932,0x6cf414a3,0xdb7928ab,0x13a3b8a3,0x4b381c1d,0xa10b54cb,
    0x55359d9d,0x35a3422a,0x58d1b551,0x0fd4de20,0x199eb3f4,0x167e09e2,0x3ee6a956,0x5371a7fa,
    0xd424efda,0x74f521c5,0xcb899ff6,0x4a42e4f4,0x747917b6,0x4b08df0b,0x090c7a39,0x11e909e4,
    0x258e2e32,0xd9fad92d,0x48fe5f69,0x0545cde6,0x55937b37,0x9b4ae4e4,0x1332b40e,0xc3792351,
    0xaff982ef,0x4dba132a,0x38b81ef1,0x28e641bf,0x227208c1,0xec4bbe37,0xc4e1821c,0x512c9d09,
    0xdaef1257,0xb63e7784,0x043e04d7,0x9c2cea47,0x45a0e59a,0x281315ca,0x849f0aac,0xa4071ed3,
    0x0ef707b3,0xfe8dac02,0x12173864,0x471f6d46,0x24a53c0a,0x35ab9265,0xbbf77406,0xa2144e79,
    0xb39a884a,0x0baf5b6d,0xcccee3dd,0x12c77584,0x2907325b,0xfd1adcd2,0xd16ee972,0x345ad6c1,
    0x315ebe66,0xc7ad2b8d,0x99e82c8d,0xe52da8c8,0xba50f1d3,0x66689cd8,0x2e8e9138,0x43e15e74,
    0xf1ced14d,0x188ec52a,0xe0ef3cbb,0xa958aedc,0x4107a1bc,0x5a9e7a3e,0x3bde939f,0xb5b28d5a,
    0x596fe848,0xe85ad00c,0x0b6b3aae,0x44503086,0x25b5695c,0xc0c31dcd,0x5ee617f0,0x74d40c3a,
    0xd2cb2b9f,0x1e19f5fa,0x81e24faf,0xa01ed68f,0xcee172fc,0x7fdf2e4d,0x002f4774,0x664f82dd,
    0xc569c39a,0xa2d4dcbe,0xaadea306,0xa4c947bf,0xa413e4e3,0x81fb5486,0x8a404970,0x752c980c,
    0x98d1d881,0x5c932c1e,0xeee65dfb,0x37592cdd,0x0fd4e65b,0xad1d383f,0x62a1452f,0x8872f68d,
    0xb58c919b,0x345c8ee3,0xb583a6d6,0x43d72cb3,0x77aaa0aa,0xeb508242,0xf2db64f8,0x86294328,
    0x82211731,0x1239a9d5,0x673ba5de,0xaf4af007,0x44203b19,0x2399d955,0xa175cd12,0x595928a7,
    0x6918928b,0xde3126bb,0x6c99835c,0x63ba1fa2,0xdebbdff0,0x3d02e541,0xd6f7aac6,0xe80b4cd0,
    0xd0fa29f1,0x804cac5e,0x2c226798,0x462f624c,0xad05b377,0x22924fcd,0xfbea205c,0x1b47586d
163 164
};

165 166


167 168 169 170 171 172 173 174
#define TAB_UNUSED 0xFFFF

typedef struct Tab_Man_t_ Tab_Man_t;
typedef struct Tab_Ent_t_ Tab_Ent_t;
struct Tab_Man_t_
{
    int         nVars;
    int         nCubes;
175 176
    int         nLits; 
    int         nTable;
177
    int *       pCubes;   // pointers to cubes
178
    word *      pValues;  // hash values
179 180 181 182 183 184 185 186 187 188 189 190 191 192
    Tab_Ent_t * pTable;   // hash table (lits -> cube + lit + lit)
    int         Degree;   // degree of 2 larger than log2(nCubes)
    int         Mask;     // table size (2^Degree)
    int         nEnts;    // number of entries
};
struct Tab_Ent_t_
{
    int         Table;
    int         Cube;
    unsigned    VarA : 16;
    unsigned    VarB : 16;
    int         Next;
};

193 194 195
static inline int *       Tab_ManCube( Tab_Man_t * p, int i ) { assert(i >= 0  && i < p->nCubes); return p->pCubes + i * (p->nVars + 1);  }
static inline Tab_Ent_t * Tab_ManEnt( Tab_Man_t * p, int i )  { assert(i >= -1 && i < p->nTable); return i >= 0 ? p->pTable + i : NULL;   }

196 197
static inline int   Tab_ManValue( Tab_Man_t * p, int a )
{
198 199
    assert( a >= 0 && a < 256 );
    return s_256Primes[a];
200 201 202 203 204
}
static inline int   Tab_ManFinal( Tab_Man_t * p, int a )
{
    return a & p->Mask;
}
205
static inline word Tab_ManHashValue( Tab_Man_t * p, int * pCube )
206
{
207
    word Value = 0; int i;
208 209 210 211
    for ( i = 1; i <= pCube[0]; i++ )
        Value += Tab_ManValue( p, pCube[i] );
    return Value;
}
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
static inline word Tab_ManHashValueWithoutVar( Tab_Man_t * p, int * pCube, int iVar )
{
    word Value = 0; int i;
    for ( i = 1; i <= pCube[0]; i++ )
        if ( i != iVar )
            Value += Tab_ManValue( p, pCube[i] );
    return Value;
}
static inline unsigned Tab_ManHashValueCube( Tab_Man_t * p, int c, int iVar )
{
    if ( iVar == 0xFFFF )
        return (unsigned)(p->pValues[c] % p->nTable);
    return (unsigned)((p->pValues[c] - Tab_ManValue(p, Tab_ManCube(p, c)[iVar+1])) % p->nTable);
}
static inline void  Tab_ManPrintCube( Tab_Man_t * p, int c, int Var )
{
    int i, * pCube = Tab_ManCube( p, c );
    for ( i = 1; i <= pCube[0]; i++ )
//        if ( i == Var + 1 )
//            printf( "-" );
//        else
            printf( "%d", !Abc_LitIsCompl(pCube[i]) );
}
235 236 237 238
static inline void  Tab_ManHashAdd( Tab_Man_t * p, int Value, int Cube, int VarA, int VarB )
{
    Tab_Ent_t * pCell = p->pTable + p->nEnts;
    Tab_Ent_t * pBin  = p->pTable + Value;
239 240 241 242 243 244
/*
    printf( "Adding cube " );
    Tab_ManPrintCube( p, Cube, VarA );
    printf( " with var %d and value %d\n", VarA, Value );
*/
    if ( pBin->Table >= 0 )
245 246 247 248 249 250 251 252
        pCell->Next = pBin->Table;
    pBin->Table = p->nEnts++;
    pCell->Cube = Cube;
    pCell->VarA = VarA;
    pCell->VarB = VarB;
}
static inline void  Tab_ManPrintEntry( Tab_Man_t * p, int e )
{
253 254 255
    printf( "Entry %10d : ", e );
    printf( "Cube %6d  ", p->pTable[e].Cube );
    printf( "Value %12u  ", Tab_ManHashValueCube(p, p->pTable[e].Cube, p->pTable[e].VarA) % p->nTable );
256 257 258 259 260 261 262 263 264 265 266
    Tab_ManPrintCube( p, p->pTable[e].Cube, p->pTable[e].VarA );
    printf( "   " );
    if ( p->pTable[e].VarA != 0xFFFF )
        printf( "%2d ", p->pTable[e].VarA );
    else
        printf( "   " );
    if ( p->pTable[e].VarB != 0xFFFF )
        printf( "%2d ", p->pTable[e].VarB );
    else
        printf( "   " );
    printf( "\n" );
267 268 269 270 271 272 273 274 275 276 277
} 
static inline void  Tab_ManHashCollectBin( Tab_Man_t * p, int Bin, Vec_Int_t * vBin )
{
    Tab_Ent_t * pEnt = p->pTable + Bin;
    Vec_IntClear( vBin );
    for ( pEnt = Tab_ManEnt(p, pEnt->Table); pEnt; pEnt = Tab_ManEnt(p, pEnt->Next) )
    {
        Vec_IntPush( vBin, pEnt - p->pTable );
        //Tab_ManPrintEntry( p, pEnt - p->pTable );
    }
    //printf( "\n" );
278 279
}

280 281 282 283 284 285 286 287 288
#define Tab_ManForEachCube( p, pCube, c )                                  \
    for ( c = 0; c < p->nCubes && (pCube = Tab_ManCube(p, c)); c++ )       \
        if ( pCube[0] == -1 ) {} else 

#define Tab_ManForEachCubeReverse( p, pCube, c )                           \
    for ( c = p->nCubes - 1; c >= 0 && (pCube = Tab_ManCube(p, c)); c-- )  \
        if ( pCube[0] == -1 ) {} else 


289 290
/**Function*************************************************************

291
  Synopsis    [Manager manipulation.]
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Tab_Man_t * Tab_ManAlloc( int nVars, int nCubes )
{
    Tab_Man_t * p = ABC_CALLOC( Tab_Man_t, 1 );
    p->nVars   = nVars;
    p->nCubes  = nCubes;
    p->Degree  = Abc_Base2Log((p->nVars + 1) * p->nCubes + 1) + 3;
    p->Mask    = (1 << p->Degree) - 1;
307 308 309 310 311
    //p->nEnts   = 1;
    p->pCubes  = ABC_CALLOC( int, p->nCubes * (p->nVars + 1) );
    p->pValues = ABC_CALLOC( word, p->nCubes );
//    p->pTable  = ABC_CALLOC( Tab_Ent_t, (p->Mask + 1) );
    printf( "Allocated %.2f MB for cube structure.\n", 4.0 * p->nCubes * (p->nVars + 2) / (1 << 20) );
312 313 314 315 316 317 318 319 320 321 322 323
    return p;
}
void Tab_ManFree( Tab_Man_t * p )
{
    ABC_FREE( p->pCubes );
    ABC_FREE( p->pValues );
    ABC_FREE( p->pTable );
    ABC_FREE( p );
}
void Tab_ManStart( Tab_Man_t * p, Vec_Int_t * vCubes )
{
    int * pCube, Cube, c, v;
324 325
    p->nLits = 0;
    Tab_ManForEachCube( p, pCube, c )
326
    {
327
        Cube = Vec_IntEntry( vCubes, c );
328 329 330 331
        pCube[0] = p->nVars;
        for ( v = 0; v < p->nVars; v++ )
            pCube[v+1] = Abc_Var2Lit( v, !((Cube >> v) & 1) );
        p->pValues[c] = Tab_ManHashValue( p, pCube );
332
        p->nLits += pCube[0];
333
    }
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
}


/**Function*************************************************************

  Synopsis    [Find a cube-free divisor of the two cubes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Tab_ManCubeFree( int * pCube1, int * pCube2, Vec_Int_t * vCubeFree )
{
    int * pBeg1 = pCube1 + 1;  // skip variable ID
    int * pBeg2 = pCube2 + 1;  // skip variable ID
    int * pEnd1 = pBeg1 + pCube1[0];
    int * pEnd2 = pBeg2 + pCube2[0];
    int Counter = 0, fAttr0 = 0, fAttr1 = 1;
    Vec_IntClear( vCubeFree );
    while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
357
    {
358 359 360 361 362
        if ( *pBeg1 == *pBeg2 )
            pBeg1++, pBeg2++, Counter++;
        else if ( *pBeg1 < *pBeg2 )
            Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg1++, fAttr0) );
        else  
363
        {
364 365 366
            if ( Vec_IntSize(vCubeFree) == 0 )
                fAttr0 = 1, fAttr1 = 0;
            Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg2++, fAttr1) );
367 368
        }
    }
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
    while ( pBeg1 < pEnd1 )
        Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg1++, fAttr0) );
    while ( pBeg2 < pEnd2 )
        Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg2++, fAttr1) );
    if ( Vec_IntSize(vCubeFree) == 0 )
        printf( "The SOP has duplicated cubes.\n" );
    else if ( Vec_IntSize(vCubeFree) == 1 )
        printf( "The SOP has contained cubes.\n" );
//    else if ( Vec_IntSize(vCubeFree) == 2 && Abc_Lit2Var(Abc_Lit2Var(Vec_IntEntry(vCubeFree, 0))) == Abc_Lit2Var(Abc_Lit2Var(Vec_IntEntry(vCubeFree, 1))) )
//        printf( "The SOP has distance-1 cubes or it is not a prime cover.  Please make sure the result verifies.\n" );
    assert( !Abc_LitIsCompl(Vec_IntEntry(vCubeFree, 0)) );
    return Counter;
}
int Tab_ManCheckEqual2( int * pCube1, int * pCube2, int Var1, int Var2 )
{
    int i1, i2;
    for ( i1 = i2 = 1; ; i1++, i2++ )
    {
        if ( i1 == Var1 )  i1++;
        if ( i2 == Var2 )  i2++;
        if ( i1 > pCube1[0] || i2 > pCube2[0] )
            return 0;
        if ( pCube1[i1] != pCube2[i2] )
            return 0;
        if ( i1 == pCube1[0] && i2 == pCube2[0] )
            return 1;
    }
}
int Tab_ManCheckEqual( int * pCube1, int * pCube2, int Var1, int Var2 )
{
    int Cube1[32], Cube2[32];
    int i, k, nVars1, nVars2;
    assert( pCube1[0] <= 32 );
    assert( pCube2[0] <= 32 );
    for ( i = 1, k = 0; i <= pCube1[0]; i++ )
        if ( i != Var1 )
            Cube1[k++] = pCube1[i];
    nVars1 = k;
    for ( i = 1, k = 0; i <= pCube2[0]; i++ )
        if ( i != Var2 )
            Cube2[k++] = pCube2[i];
    nVars2 = k;
    if ( nVars1 != nVars2 )
        return 0;
    for ( i = 0; i < nVars1; i++ )
        if ( Cube1[i] != Cube2[i] )
            return 0;
    return 1;
417 418
}

419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
/**Function*************************************************************

  Synopsis    [Collecting distance-1 pairs.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Tab_ManCountItems( Tab_Man_t * p, int Dist2, Vec_Int_t ** pvStarts )
{
    Vec_Int_t * vStarts = Vec_IntAlloc( p->nCubes );
    int * pCube, c, Count = 0;
    Tab_ManForEachCube( p, pCube, c )
    {
        Vec_IntPush( vStarts, Count );
        Count += 1 + pCube[0];
        if ( Dist2 )
            Count += pCube[0] * pCube[0] / 2;
    }
    assert( Vec_IntSize(vStarts) == p->nCubes );
    if ( pvStarts )
        *pvStarts = vStarts;
    return Count;
}
Vec_Int_t * Tab_ManCollectDist1( Tab_Man_t * p, int Dist2 )
{
    Vec_Int_t * vStarts = NULL;                           // starting mark for each cube
    int nItems = Tab_ManCountItems( p, Dist2, &vStarts ); // item count
    int nBits  = Abc_Base2Log( nItems ) + 6;              // hash table size  
    Vec_Bit_t * vPres = Vec_BitStart( 1 << nBits );       // hash table
    Vec_Bit_t * vMarks = Vec_BitStart( nItems );          // collisions 
    Vec_Int_t * vUseful = Vec_IntAlloc( 1000 );           // useful pairs
    Vec_Int_t * vBin = Vec_IntAlloc( 100 );
    Vec_Int_t * vCubeFree = Vec_IntAlloc( 100 );
    word Value; unsigned Mask = (1 << nBits) - 1;
    int * pCube, c, a, b, nMarks = 0, nUseful, Entry1, Entry2;
    // iterate forward
    Tab_ManForEachCube( p, pCube, c )
    {
        // cube
        if ( Vec_BitAddEntry(vPres, (int)p->pValues[c] & Mask) )
            Vec_BitWriteEntry( vMarks, nMarks, 1 );
        nMarks++;
        // dist1
        for ( a = 1; a <= pCube[0]; a++, nMarks++ )
            if ( Vec_BitAddEntry(vPres, (int)(p->pValues[c] - Tab_ManValue(p, pCube[a])) & Mask) )
                Vec_BitWriteEntry( vMarks, nMarks, 1 );
        // dist2
        if ( Dist2 )
        for ( a = 1; a <= pCube[0]; a++ )
        {
            Value = p->pValues[c] - Tab_ManValue(p, pCube[a]);
            for ( b = a + 1; b <= pCube[0]; b++, nMarks++ )
                if ( Vec_BitAddEntry(vPres, (int)(Value - Tab_ManValue(p, pCube[b])) & Mask) )
                    Vec_BitWriteEntry( vMarks, nMarks, 1 );
        }
    }
    assert( nMarks == nItems );
    Vec_BitReset( vPres );
    // iterate backward
    nMarks--;
    Tab_ManForEachCubeReverse( p, pCube, c )
    {
        Value = p->pValues[c];
        // dist2
        if ( Dist2 )
        for ( a = pCube[0]; a >= 1; a-- )
        {
            Value = p->pValues[c] - Tab_ManValue(p, pCube[a]);
            for ( b = pCube[0]; b >= a + 1; b--, nMarks-- )
                if ( Vec_BitAddEntry(vPres, (int)(Value - Tab_ManValue(p, pCube[b])) & Mask) )
                    Vec_BitWriteEntry( vMarks, nMarks, 1 );
        }
        // dist1
        for ( a = pCube[0]; a >= 1; a--, nMarks-- )
            if ( Vec_BitAddEntry(vPres, (int)(p->pValues[c] - Tab_ManValue(p, pCube[a])) & Mask) )
                Vec_BitWriteEntry( vMarks, nMarks, 1 );
        // cube
        if ( Vec_BitAddEntry(vPres, (int)p->pValues[c] & Mask) )
            Vec_BitWriteEntry( vMarks, nMarks, 1 );
        nMarks--;
    }
    nMarks++;
    assert( nMarks == 0 );
    Vec_BitFree( vPres );
    // count useful
    nUseful = Vec_BitCount( vMarks );
printf( "Items = %d. Bits = %d.   Useful = %d.   \n", nItems, nBits, nUseful );

    // add to the hash table
    p->nTable = Abc_PrimeCudd(nUseful);
    p->pTable = ABC_FALLOC( Tab_Ent_t, p->nTable );
printf( "Table %d\n", p->nTable );
    Tab_ManForEachCube( p, pCube, c )
    {
        // cube
        if ( Vec_BitEntry(vMarks, nMarks++) )
            Tab_ManHashAdd( p, (int)(p->pValues[c] % p->nTable), c, TAB_UNUSED, TAB_UNUSED );
        // dist1
        for ( a = 1; a <= pCube[0]; a++, nMarks++ )
            if ( Vec_BitEntry(vMarks, nMarks) )
                Tab_ManHashAdd( p, (int)((p->pValues[c] - Tab_ManValue(p, pCube[a])) % p->nTable), c, a-1, TAB_UNUSED );
        // dist2
        if ( Dist2 )
        for ( a = 1; a <= pCube[0]; a++ )
        {
            Value = p->pValues[c] - Tab_ManValue(p, pCube[a]);
            for ( b = a + 1; b <= pCube[0]; b++, nMarks++ )
                if ( Vec_BitEntry(vMarks, nMarks) )
                    Tab_ManHashAdd( p, (int)((Value - Tab_ManValue(p, pCube[b])) % p->nTable), c, a-1, b-1 );
        }
    }
    assert( nMarks == nItems );
    // collect entries
    for ( c = 0; c < p->nTable; c++ )
    {
        Tab_ManHashCollectBin( p, c, vBin );
        //printf( "%d ", Vec_IntSize(vBin) );
        //if ( c > 100 )
        //    break;
        Vec_IntForEachEntry( vBin, Entry1, a )
        Vec_IntForEachEntryStart( vBin, Entry2, b, a + 1 )
        {
            Tab_Ent_t * pEntA = Tab_ManEnt( p, Entry1 );
            Tab_Ent_t * pEntB = Tab_ManEnt( p, Entry2 );
            int * pCubeA = Tab_ManCube( p, pEntA->Cube );
            int * pCubeB = Tab_ManCube( p, pEntB->Cube );
//            int Base = Tab_ManCubeFree( pCubeA, pCubeB, vCubeFree );
//            if ( Vec_IntSize(vCubeFree) == 2 )
            if ( Tab_ManCheckEqual(pCubeA, pCubeB, pEntA->VarA+1, pEntB->VarA+1) )
            {
                Vec_IntPushTwo( vUseful, pEntA->Cube, pEntB->Cube );
            }
        }

    }
    //printf( "\n" );

    ABC_FREE( p->pTable );
    Vec_IntFree( vCubeFree );
    Vec_IntFree( vBin );
    Vec_BitFree( vMarks );
    return vUseful;
}
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581

/**Function*************************************************************

  Synopsis    [Table decomposition.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Tab_DecomposeTest()
{
    int nVars = 20;// no more than 13
    abctime clk = Abc_Clock();
582
    Vec_Int_t * vPairs;
583 584 585
    Vec_Int_t * vPrimes = Abc_GenPrimes( nVars );
    Tab_Man_t * p = Tab_ManAlloc( nVars, Vec_IntSize(vPrimes) );
    Tab_ManStart( p, vPrimes );
586 587 588 589
    printf( "Created %d cubes dependent on %d variables with %d literals.\n", p->nCubes, p->nVars );
    vPairs = Tab_ManCollectDist1( p, 0 );
    printf( "Collected %d pairs.\n", Vec_IntSize(vPairs)/2 );
    Vec_IntFree( vPairs );
590 591 592 593 594 595
    Tab_ManFree( p );
    Vec_IntFree( vPrimes );
    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}


596 597 598 599 600 601 602
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END