FxchSCHashTable.c 12.4 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 28 29 30 31 32 33 34 35 36 37
/**CFile****************************************************************

  FileName    [ FxchSCHashTable.c ]

  PackageName [ Fast eXtract with Cube Hashing (FXCH) ]

  Synopsis    [ Sub-cubes hash table implementation ]

  Author      [ Bruno Schmitt - boschmitt at inf.ufrgs.br ]

  Affiliation [ UFRGS ]

  Date        [ Ver. 1.0. Started - March 6, 2016. ]

  Revision    []

***********************************************************************/
#include "Fxch.h"

ABC_NAMESPACE_IMPL_START

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////
static inline void MurmurHash3_x86_32 ( const void* key,
                                        int len,
                                        uint32_t seed,
                                        void* out )
{
    const uint8_t* data = (const uint8_t*)key;
    const int nblocks = len / 4;

    uint32_t h1 = seed;

    const uint32_t c1 = 0xcc9e2d51;
    const uint32_t c2 = 0x1b873593;

38 39 40
    const uint8_t * tail;
    uint32_t k1;

41 42 43 44
    //----------
    // body

    const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
45
    int i;
46

47
    for(i = -nblocks; i; i++)
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
    {
        uint32_t k1 = blocks[i];

        k1 *= c1;
        k1 = (k1 << 15) | (k1 >> (32 - 15));
        k1 *= c2;

        h1 ^= k1;
        h1 = (h1 << 13) | (h1 >> (32 - 13));
        h1 = h1*5+0xe6546b64;
    }

    //----------
    // tail

63
    tail = (const uint8_t*)(data + nblocks*4);
64

65
    k1 = 0;
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92

    switch(len & 3)
    {
        case 3: k1 ^= tail[2] << 16;
        case 2: k1 ^= tail[1] << 8;
        case 1: k1 ^= tail[0];
              k1 *= c1; k1 = (k1 << 15) | (k1 >> (32 - 15)); k1 *= c2; h1 ^= k1;
    };

    //----------
    // finalization

    h1 ^= len;

    h1 ^= h1 >> 16;
    h1 *= 0x85ebca6b;
    h1 ^= h1 >> 13;
    h1 *= 0xc2b2ae35;
    h1 ^= h1 >> 16;

    *(uint32_t*)out = h1;
}

Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan,
                                            int nEntries )
{
    Fxch_SCHashTable_t* pSCHashTable = ABC_CALLOC( Fxch_SCHashTable_t, 1 );
93
    int nBits = Abc_Base2Log( nEntries + 1 );
94 95 96 97 98 99 100 101 102 103 104


    pSCHashTable->pFxchMan = pFxchMan;
    pSCHashTable->SizeMask = (1 << nBits) - 1;
    pSCHashTable->pBins = ABC_CALLOC( Fxch_SCHashTable_Entry_t, pSCHashTable->SizeMask + 1 );

    return pSCHashTable;
}

void Fxch_SCHashTableDelete( Fxch_SCHashTable_t* pSCHashTable )
{
105 106 107
    unsigned i;
    for ( i = 0; i <= pSCHashTable->SizeMask; i++ )
        ABC_FREE( pSCHashTable->pBins[i].vSCData );
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
    Vec_IntErase( &pSCHashTable->vSubCube0 );
    Vec_IntErase( &pSCHashTable->vSubCube1 );
    ABC_FREE( pSCHashTable->pBins );
    ABC_FREE( pSCHashTable );
}

static inline Fxch_SCHashTable_Entry_t* Fxch_SCHashTableBin( Fxch_SCHashTable_t* pSCHashTable,
                                                             unsigned int SubCubeID )
{
    return pSCHashTable->pBins + (SubCubeID & pSCHashTable->SizeMask);
}

static inline int Fxch_SCHashTableEntryCompare( Fxch_SCHashTable_t* pSCHashTable,
                                                Vec_Wec_t* vCubes,
                                                Fxch_SubCube_t* pSCData0,
                                                Fxch_SubCube_t* pSCData1 )
{
    Vec_Int_t* vCube0 = Vec_WecEntry( vCubes, pSCData0->iCube ),
             * vCube1 = Vec_WecEntry( vCubes, pSCData1->iCube );

128 129
    int* pOutputID0 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pSCData0->iCube * pSCHashTable->pFxchMan->nSizeOutputID ),
       * pOutputID1 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pSCData1->iCube * pSCHashTable->pFxchMan->nSizeOutputID );
130
    int i, Result = 0;
131

132 133 134 135 136 137
    if ( !Vec_IntSize( vCube0 ) ||
         !Vec_IntSize( vCube1 ) ||
         Vec_IntEntry( vCube0, 0 ) != Vec_IntEntry( vCube1, 0 ) ||
         pSCData0->Id != pSCData1->Id )
        return 0;

138
    for ( i = 0; i < pSCHashTable->pFxchMan->nSizeOutputID && Result == 0; i++ )
139 140 141 142 143
        Result = ( pOutputID0[i] & pOutputID1[i] );

    if ( Result == 0 )
        return 0;

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
    Vec_IntClear( &pSCHashTable->vSubCube0 );
    Vec_IntClear( &pSCHashTable->vSubCube1 );

    if ( pSCData0->iLit1 > 0 && pSCData1->iLit1 > 0 &&
         ( Vec_IntEntry( vCube0, pSCData0->iLit0 ) == Vec_IntEntry( vCube1, pSCData1->iLit0 ) ||
           Vec_IntEntry( vCube0, pSCData0->iLit0 ) == Vec_IntEntry( vCube1, pSCData1->iLit1 ) ||
           Vec_IntEntry( vCube0, pSCData0->iLit1 ) == Vec_IntEntry( vCube1, pSCData1->iLit0 ) ||
           Vec_IntEntry( vCube0, pSCData0->iLit1 ) == Vec_IntEntry( vCube1, pSCData1->iLit1 ) ) )
        return 0;

    if ( pSCData0->iLit0 > 0 )
        Vec_IntAppendSkip( &pSCHashTable->vSubCube0, vCube0, pSCData0->iLit0 );
    else
        Vec_IntAppend( &pSCHashTable->vSubCube0, vCube0 );

    if ( pSCData1->iLit0 > 0 )
        Vec_IntAppendSkip( &pSCHashTable->vSubCube1, vCube1, pSCData1->iLit0 );
    else
        Vec_IntAppend( &pSCHashTable->vSubCube1, vCube1 );

    if ( pSCData0->iLit1 > 0)
        Vec_IntDrop( &pSCHashTable->vSubCube0,
                       pSCData0->iLit0 < pSCData0->iLit1 ? pSCData0->iLit1 - 1 : pSCData0->iLit1 );

    if ( pSCData1->iLit1 > 0 )
        Vec_IntDrop( &pSCHashTable->vSubCube1,
                       pSCData1->iLit0 < pSCData1->iLit1 ? pSCData1->iLit1 - 1 : pSCData1->iLit1 );

    return Vec_IntEqual( &pSCHashTable->vSubCube0, &pSCHashTable->vSubCube1 );
}

int Fxch_SCHashTableInsert( Fxch_SCHashTable_t* pSCHashTable,
                            Vec_Wec_t* vCubes,
177 178 179 180
                            uint32_t SubCubeID,
                            uint32_t iCube,
                            uint32_t iLit0,
                            uint32_t iLit1,
181 182
                            char fUpdate )
{
183 184 185 186
    int iNewEntry;
    int Pairs = 0;
    uint32_t BinID;
    Fxch_SCHashTable_Entry_t* pBin;
187 188
    Fxch_SubCube_t* pNewEntry;
    int iEntry;
189

190
    MurmurHash3_x86_32( ( void* ) &SubCubeID, sizeof( int ), 0x9747b28c, &BinID);
191
    pBin = Fxch_SCHashTableBin( pSCHashTable, BinID );
Bruno Schmitt committed
192

193 194 195 196 197 198 199 200
    if ( pBin->vSCData == NULL )
    {
        pBin->vSCData = ABC_CALLOC( Fxch_SubCube_t, 16 );
        pBin->Size = 0;
        pBin->Cap = 16;
    }
    else if ( pBin->Size == pBin->Cap )
    {
201 202
        assert(pBin->Cap <= 0xAAAA);
        pBin->Cap = ( pBin->Cap >> 1 ) * 3;
203 204
        pBin->vSCData = ABC_REALLOC( Fxch_SubCube_t, pBin->vSCData, pBin->Cap );
    }
205

206 207 208 209 210
    iNewEntry = pBin->Size++;
    pBin->vSCData[iNewEntry].Id = SubCubeID;
    pBin->vSCData[iNewEntry].iCube = iCube;
    pBin->vSCData[iNewEntry].iLit0 = iLit0;
    pBin->vSCData[iNewEntry].iLit1 = iLit1;
211
    pSCHashTable->nEntries++;
212 213

    if ( pBin->Size == 1 )
214 215
        return 0;

216 217
    pNewEntry = &( pBin->vSCData[iNewEntry] );
    for ( iEntry = 0; iEntry < (int)pBin->Size - 1; iEntry++ )
218
    {
219 220 221 222
        Fxch_SubCube_t* pEntry = &( pBin->vSCData[iEntry] );
        int* pOutputID0 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID );
        int* pOutputID1 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pNewEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID );
        int Result = 0;
223
        int Base;
Alan Mishchenko committed
224
        int iNewDiv = -1, i, z;
225

Bruno Schmitt committed
226 227 228
        if ( (pEntry->iLit1 != 0 && pNewEntry->iLit1 == 0) || (pEntry->iLit1 == 0 && pNewEntry->iLit1 != 0)  )
            continue;

229
        if ( !Fxch_SCHashTableEntryCompare( pSCHashTable, vCubes, pEntry, pNewEntry ) )
230 231
            continue;

232
        if ( ( pEntry->iLit0 == 0 ) || ( pNewEntry->iLit0 == 0 ) )
233
        {
234 235
            Vec_Int_t* vCube0 = Fxch_ManGetCube( pSCHashTable->pFxchMan, pEntry->iCube ),
                     * vCube1 = Fxch_ManGetCube( pSCHashTable->pFxchMan, pNewEntry->iCube );
Bruno Schmitt committed
236

237
            if ( Vec_IntSize( vCube0 ) > Vec_IntSize( vCube1 ) )
238 239 240 241
            {
                Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pEntry->iCube );
                Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pNewEntry->iCube );
            }
242
            else
243 244 245 246
            {
                Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pNewEntry->iCube );
                Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pEntry->iCube );
            }
247

248 249 250
            continue;
        }

251
        Base = Fxch_DivCreate( pSCHashTable->pFxchMan, pEntry, pNewEntry );
252

253
        if ( Base < 0 )
254 255
            continue;

256
        for ( i = 0; i < pSCHashTable->pFxchMan->nSizeOutputID; i++ )
257 258
            Result += Fxch_CountOnes( pOutputID0[i] & pOutputID1[i] );

259
        for ( z = 0; z < Result; z++ )
260
            iNewDiv = Fxch_DivAdd( pSCHashTable->pFxchMan, fUpdate, 0, Base );
261

262 263
        Vec_WecPush( pSCHashTable->pFxchMan->vDivCubePairs, iNewDiv, pEntry->iCube );
        Vec_WecPush( pSCHashTable->pFxchMan->vDivCubePairs, iNewDiv, pNewEntry->iCube );
264 265 266 267 268 269 270 271 272

        Pairs++;
    }

    return Pairs;
}

int Fxch_SCHashTableRemove( Fxch_SCHashTable_t* pSCHashTable,
                            Vec_Wec_t* vCubes,
273 274 275 276
                            uint32_t SubCubeID,
                            uint32_t iCube,
                            uint32_t iLit0,
                            uint32_t iLit1,
277 278
                            char fUpdate )
{
279 280 281 282
    int iEntry;
    int Pairs = 0;
    uint32_t BinID;
    Fxch_SCHashTable_Entry_t* pBin;
283 284
    Fxch_SubCube_t* pEntry;
    int idx;
285

286
    MurmurHash3_x86_32( ( void* ) &SubCubeID, sizeof( int ), 0x9747b28c, &BinID);
287

288
    pBin = Fxch_SCHashTableBin( pSCHashTable, BinID );
289

290
    if ( pBin->Size == 1 )
291
    {
292
        pBin->Size = 0;
293 294 295
        return 0;
    }

296
    for ( iEntry = 0; iEntry < (int)pBin->Size; iEntry++ )
297 298 299
        if ( pBin->vSCData[iEntry].iCube == iCube )
            break;

Alan Mishchenko committed
300
    assert( ( iEntry != (int)pBin->Size ) && ( pBin->Size != 0 ) );
301

302 303 304
    pEntry = &( pBin->vSCData[iEntry] );
    for ( idx = 0; idx < (int)pBin->Size; idx++ )
    if ( idx != iEntry )
305
    {
306
        int Base,
Alan Mishchenko committed
307
            iDiv = -1;
308

309
        int i, z,
310 311 312
            iCube0,
            iCube1;

313
        Fxch_SubCube_t* pNextEntry = &( pBin->vSCData[idx] );
314
        Vec_Int_t* vDivCubePairs;
315 316 317
        int* pOutputID0 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID );
        int* pOutputID1 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pNextEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID );
        int Result = 0;
318

Bruno Schmitt committed
319 320 321
        if ( (pEntry->iLit1 != 0 && pNextEntry->iLit1 == 0) || (pEntry->iLit1 == 0 && pNextEntry->iLit1 != 0)  )
            continue;

322 323 324
        if ( !Fxch_SCHashTableEntryCompare( pSCHashTable, vCubes, pEntry, pNextEntry )
             || pEntry->iLit0 == 0
             || pNextEntry->iLit0 == 0 )
325 326
            continue;

327
        Base = Fxch_DivCreate( pSCHashTable->pFxchMan, pNextEntry, pEntry );
328

329
        if ( Base < 0 )
330 331
            continue;

332
        for ( i = 0; i < pSCHashTable->pFxchMan->nSizeOutputID; i++ )
333 334
            Result += Fxch_CountOnes( pOutputID0[i] & pOutputID1[i] );

335
        for ( z = 0; z < Result; z++ )
336
            iDiv = Fxch_DivRemove( pSCHashTable->pFxchMan, fUpdate, 0, Base );
337

338
        vDivCubePairs = Vec_WecEntry( pSCHashTable->pFxchMan->vDivCubePairs, iDiv );
339
        Vec_IntForEachEntryDouble( vDivCubePairs, iCube0, iCube1, i )
340 341
            if ( ( iCube0 == (int)pNextEntry->iCube && iCube1 == (int)pEntry->iCube )  ||
                 ( iCube0 == (int)pEntry->iCube && iCube1 == (int)pNextEntry->iCube ) )
342 343 344 345 346 347
            {
                Vec_IntDrop( vDivCubePairs, i+1 );
                Vec_IntDrop( vDivCubePairs, i );
            }
        if ( Vec_IntSize( vDivCubePairs ) == 0 )
            Vec_IntErase( vDivCubePairs );
348 349 350

        Pairs++;
    }
Bruno Schmitt committed
351

352 353
    memmove(pBin->vSCData + iEntry, pBin->vSCData + iEntry + 1, (pBin->Size - iEntry - 1) * sizeof(*pBin->vSCData));
    pBin->Size -= 1;
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368

    return Pairs;
}

unsigned int Fxch_SCHashTableMemory( Fxch_SCHashTable_t* pHashTable )
{
    unsigned int Memory = sizeof ( Fxch_SCHashTable_t );

    Memory += sizeof( Fxch_SubCube_t ) * ( pHashTable->SizeMask + 1 );

    return Memory;
}

void Fxch_SCHashTablePrint( Fxch_SCHashTable_t* pHashTable )
{
369
    int Memory;
370 371 372 373
    printf( "SubCube Hash Table at %p\n", ( void* )pHashTable );
    printf("%20s %20s\n", "nEntries",
                          "Memory Usage (MB)" );

374
    Memory = Fxch_SCHashTableMemory( pHashTable );
375 376 377 378 379 380 381 382
    printf("%20d %18.2f\n", pHashTable->nEntries,
                            ( ( double ) Memory / 1048576 ) );
}
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////

ABC_NAMESPACE_IMPL_END