Exemple #1
0
    // Given a position, produce a 64-bit material signature key.
    // If the engine supports such a key, it should equal the engine's key.
    internal static ulong calc_key(Position pos, int mirror)
    {
        Color     color;
        PieceType pt;
        int       i;
        ulong     key = 0;

        color = mirror == 0 ? Color.WHITE : Color.BLACK;
        for (pt = PieceType.PAWN; pt <= PieceType.KING; ++pt)
        {
            for (i = GlobalMembersTbprobe.popcount <Max15>(pos.pieces(color, pt)); i > 0; i--)
            {
                key ^= Zobrist.psq[(int)Color.WHITE][(int)pt][i - 1];
            }
        }
        color = ~color;
        for (pt = PieceType.PAWN; pt <= PieceType.KING; ++pt)
        {
            for (i = GlobalMembersTbprobe.popcount <Max15>(pos.pieces(color, pt)); i > 0; i--)
            {
                key ^= Zobrist.psq[(int)Color.BLACK][(int)pt][i - 1];
            }
        }

        return(key);
    }
Exemple #2
0
    // Given a position with 6 or fewer pieces, produce a text string
    // of the form KQPvKRP, where "KQP" represents the white pieces if
    // mirror == 0 and the black pieces if mirror == 1.
//C++ TO C# CONVERTER TODO TASK: Pointer arithmetic is detected on the parameter 'str', so pointers on this parameter are left unchanged:
    internal static void prt_str(Position pos, sbyte *str, int mirror)
    {
        Color     color;
        PieceType pt;
        int       i;

        color = mirror == 0 ? Color.WHITE : Color.BLACK;
        for (pt = PieceType.KING; pt >= PieceType.PAWN; --pt)
        {
            for (i = GlobalMembersTbprobe.popcount <Max15>(pos.pieces(color, pt)); i > 0; i--)
            {
                *str++ = GlobalMembersTbcore.pchr[6 - pt];
            }
        }
        *str++ = 'v';
        color = ~color;
        for (pt = PieceType.KING; pt >= PieceType.PAWN; --pt)
        {
            for (i = GlobalMembersTbprobe.popcount <Max15>(pos.pieces(color, pt)); i > 0; i--)
            {
                *str++ = GlobalMembersTbcore.pchr[6 - pt];
            }
        }
        *str++ = 0;
    }
Exemple #3
0
    internal static void init_tb(ref string str)
    {
        FD      fd = new FD();
        TBEntry entry;
        int     i;
        int     j;

        int[] pcs = new int[16];
        ulong key;
        ulong key2;
        int   color;
//C++ TO C# CONVERTER TODO TASK: Pointer arithmetic is detected on this variable, so pointers on this variable are left unchanged:
        sbyte *s;

        fd = GlobalMembersTbcore.open_tb(str, DefineConstants.WDLSUFFIX);
        if (fd == DefineConstants.FD_ERR)
        {
            return;
        }
        GlobalMembersTbcore.close_tb(fd);

        for (i = 0; i < 16; i++)
        {
            pcs[i] = 0;
        }
        color = 0;
        for (s = str; *s; s++)
        {
            switch (*s)
            {
            case 'P':
                pcs[DefineConstants.TB_PAWN | color]++;
                break;

            case 'N':
                pcs[DefineConstants.TB_KNIGHT | color]++;
                break;

            case 'B':
                pcs[DefineConstants.TB_BISHOP | color]++;
                break;

            case 'R':
                pcs[DefineConstants.TB_ROOK | color]++;
                break;

            case 'Q':
                pcs[DefineConstants.TB_QUEEN | color]++;
                break;

            case 'K':
                pcs[DefineConstants.TB_KING | color]++;
                break;

            case 'v':
                color = 0x08;
                break;
            }
        }
        for (i = 0; i < 8; i++)
        {
            if (pcs[i] != pcs[i + 8])
            {
                break;
            }
        }
        key  = GlobalMembersTbprobe.calc_key_from_pcs(pcs, 0);
        key2 = GlobalMembersTbprobe.calc_key_from_pcs(pcs, 1);
        if (pcs[DefineConstants.TB_PAWN] + pcs[DefineConstants.TB_PAWN | 8] == 0)
        {
            if (TBnum_piece == DefineConstants.TBMAX_PIECE)
            {
                Console.Write("TBMAX_PIECE limit too low!\n");
                Environment.Exit(1);
            }
            entry = (TBEntry)TB_piece[TBnum_piece++];
        }
        else
        {
            if (TBnum_pawn == DefineConstants.TBMAX_PAWN)
            {
                Console.Write("TBMAX_PAWN limit too low!\n");
                Environment.Exit(1);
            }
            entry = (TBEntry)TB_pawn[TBnum_pawn++];
        }
        entry.key   = key;
        entry.ready = 0;
        entry.num   = 0;
        for (i = 0; i < 16; i++)
        {
            entry.num += (byte)pcs[i];
        }
        entry.symmetric = (key == key2);
        entry.has_pawns = (pcs[DefineConstants.TB_PAWN] + pcs[DefineConstants.TB_PAWN | 8] > 0);
        if (entry.num > GlobalMembersTbprobe.MaxCardinality)
        {
            GlobalMembersTbprobe.MaxCardinality = entry.num;
        }

        if (entry.has_pawns != 0)
        {
            TBEntry_pawn ptr = (TBEntry_pawn)entry;
            ptr.pawns[0] = (byte)pcs[DefineConstants.TB_PAWN];
            ptr.pawns[1] = (byte)pcs[DefineConstants.TB_PAWN | 8];
            if (pcs[DefineConstants.TB_PAWN | 8] > 0 && (pcs[DefineConstants.TB_PAWN] == 0 || pcs[DefineConstants.TB_PAWN | 8] < pcs[DefineConstants.TB_PAWN]))
            {
                ptr.pawns[0] = (byte)pcs[DefineConstants.TB_PAWN | 8];
                ptr.pawns[1] = (byte)pcs[DefineConstants.TB_PAWN];
            }
        }
        else
        {
            TBEntry_piece ptr = (TBEntry_piece)entry;
            for (i = 0, j = 0; i < 16; i++)
            {
                if (pcs[i] == 1)
                {
                    j++;
                }
            }
            if (j >= 3)
            {
                ptr.enc_type = 0;
            }
            else if (j == 2)
            {
                ptr.enc_type = 2;
            }
            else     // only for suicide
            {
                j = 16;
                for (i = 0; i < 16; i++)
                {
                    if (pcs[i] < j && pcs[i] > 1)
                    {
                        j = pcs[i];
                    }
                    ptr.enc_type = (byte)(1 + j);
                }
            }
        }
        GlobalMembersTbcore.add_to_hash(entry, key);
        if (key2 != key)
        {
            GlobalMembersTbcore.add_to_hash(entry, key2);
        }
    }
Exemple #4
0
    // This routine treats a position with en passant captures as one without.
    internal static int probe_dtz_no_ep(Position pos, ref int success)
    {
        int wdl;
        int dtz;

        wdl = GlobalMembersTbprobe.probe_ab(pos, -2, 2, ref success);
        if (success == 0)
        {
            return(0);
        }

        if (wdl == 0)
        {
            return(0);
        }

        if (success == 2)
        {
            return(wdl == 2 ? 1 : 101);
        }

        ExtMove[] stack = Arrays.InitializeWithDefaultInstances <ExtMove>(192);
//C++ TO C# CONVERTER TODO TASK: Pointer arithmetic is detected on this variable, so pointers on this variable are left unchanged:
        ExtMove * moves = new ExtMove();
        ExtMove   end   = null;
        StateInfo st    = new StateInfo();
        CheckInfo ci    = new CheckInfo(pos);

        if (wdl > 0)
        {
            // Generate at least all legal non-capturing pawn moves
            // including non-capturing promotions.
            if (pos.checkers() == 0)
            {
//C++ TO C# CONVERTER WARNING: The following line was determined to be a copy constructor call - this should be verified and a copy constructor should be created if it does not yet exist:
//ORIGINAL LINE: end = generate<NON_EVASIONS>(pos, stack);
                end = GlobalMembersMovegen.generate <GenType.NON_EVASIONS>(pos, new ExtMove(stack));
            }
            else
            {
//C++ TO C# CONVERTER WARNING: The following line was determined to be a copy constructor call - this should be verified and a copy constructor should be created if it does not yet exist:
//ORIGINAL LINE: end = generate<EVASIONS>(pos, stack);
                end = GlobalMembersMovegen.generate <GenType.EVASIONS>(pos, new ExtMove(stack));
            }

            for (moves = stack; moves < end; moves++)
            {
                Move move = moves.move;
                if (GlobalMembersTypes.type_of(pos.moved_piece(move)) != PieceType.PAWN || pos.capture(move) || !pos.legal(move, ci.pinned))
                {
                    continue;
                }
                pos.do_move(move, st, ci, pos.gives_check(move, ci));
                int v = -GlobalMembersTbprobe.probe_ab(pos, -2, -wdl + 1, ref success);
                pos.undo_move(move);
                if (success == 0)
                {
                    return(0);
                }
                if (v == wdl)
                {
                    return(v == 2 ? 1 : 101);
                }
            }
        }

        dtz = 1 + GlobalMembersTbprobe.probe_dtz_table(pos, wdl, ref success);
        if (success >= 0)
        {
            if ((wdl & 1) != 0)
            {
                dtz += 100;
            }
            return(wdl >= 0 ? dtz : -dtz);
        }

        if (wdl > 0)
        {
            int best = 0xffff;
            for (moves = stack; moves < end; moves++)
            {
                Move move = moves.move;
                if (pos.capture(move) || GlobalMembersTypes.type_of(pos.moved_piece(move)) == PieceType.PAWN || !pos.legal(move, ci.pinned))
                {
                    continue;
                }
                pos.do_move(move, st, ci, pos.gives_check(move, ci));
                int v = -GlobalMembersTbprobe.probe_dtz(pos, ref success);
                pos.undo_move(move);
                if (success == 0)
                {
                    return(0);
                }
                if (v > 0 && v + 1 < best)
                {
                    best = v + 1;
                }
            }
            return(best);
        }
        else
        {
            int best = -1;
            if (pos.checkers() == 0)
            {
//C++ TO C# CONVERTER WARNING: The following line was determined to be a copy constructor call - this should be verified and a copy constructor should be created if it does not yet exist:
//ORIGINAL LINE: end = generate<NON_EVASIONS>(pos, stack);
                end = GlobalMembersMovegen.generate <GenType.NON_EVASIONS>(pos, new ExtMove(stack));
            }
            else
            {
//C++ TO C# CONVERTER WARNING: The following line was determined to be a copy constructor call - this should be verified and a copy constructor should be created if it does not yet exist:
//ORIGINAL LINE: end = generate<EVASIONS>(pos, stack);
                end = GlobalMembersMovegen.generate <GenType.EVASIONS>(pos, new ExtMove(stack));
            }
            for (moves = stack; moves < end; moves++)
            {
                int  v;
                Move move = moves.move;
                if (!pos.legal(move, ci.pinned))
                {
                    continue;
                }
                pos.do_move(move, st, ci, pos.gives_check(move, ci));
                if (st.rule50 == 0)
                {
                    if (wdl == -2)
                    {
                        v = -1;
                    }
                    else
                    {
                        v = GlobalMembersTbprobe.probe_ab(pos, 1, 2, ref success);
                        v = (v == 2) ? 0 : -101;
                    }
                }
                else
                {
                    v = -GlobalMembersTbprobe.probe_dtz(pos, ref success) - 1;
                }
                pos.undo_move(move);
                if (success == 0)
                {
                    return(0);
                }
                if (v < best)
                {
                    best = v;
                }
            }
            return(best);
        }
    }
Exemple #5
0
    internal static int probe_ab(Position pos, int alpha, int beta, ref int success)
    {
        int v;

        ExtMove[] stack = Arrays.InitializeWithDefaultInstances <ExtMove>(64);
        ExtMove   moves;
        ExtMove   end;
        StateInfo st = new StateInfo();

        // Generate (at least) all legal non-ep captures including (under)promotions.
        // It is OK to generate more, as long as they are filtered out below.
        if (pos.checkers() == 0)
        {
//C++ TO C# CONVERTER WARNING: The following line was determined to be a copy constructor call - this should be verified and a copy constructor should be created if it does not yet exist:
//ORIGINAL LINE: end = generate<CAPTURES>(pos, stack);
            end = GlobalMembersMovegen.generate <GenType.CAPTURES>(pos, new ExtMove(stack));
            // Since underpromotion captures are not included, we need to add them.
//C++ TO C# CONVERTER WARNING: The following line was determined to be a copy constructor call - this should be verified and a copy constructor should be created if it does not yet exist:
//ORIGINAL LINE: end = add_underprom_caps(pos, stack, end);
            end = GlobalMembersTbprobe.add_underprom_caps(pos, new ExtMove(stack), end);
        }
        else
        {
//C++ TO C# CONVERTER WARNING: The following line was determined to be a copy constructor call - this should be verified and a copy constructor should be created if it does not yet exist:
//ORIGINAL LINE: end = generate<EVASIONS>(pos, stack);
            end = GlobalMembersMovegen.generate <GenType.EVASIONS>(pos, new ExtMove(stack));
        }

        CheckInfo ci = new CheckInfo(pos);

        for (moves = stack; moves < end; moves++)
        {
            Move capture = moves.move;
            if (!pos.capture(capture) || GlobalMembersTypes.type_of(capture) == MoveType.ENPASSANT || !pos.legal(capture, ci.pinned))
            {
                continue;
            }
            pos.do_move(capture, st, ci, pos.gives_check(capture, ci));
            v = -GlobalMembersTbprobe.probe_ab(pos, -beta, -alpha, ref success);
            pos.undo_move(capture);
            if (success == 0)
            {
                return(0);
            }
            if (v > alpha)
            {
                if (v >= beta)
                {
                    success = 2;
                    return(v);
                }
                alpha = v;
            }
        }

        v = GlobalMembersTbprobe.probe_wdl_table(pos, ref success);
        if (success == 0)
        {
            return(0);
        }
        if (alpha >= v)
        {
            success = 1 + (alpha > 0);
            return(alpha);
        }
        else
        {
            success = 1;
            return(v);
        }
    }
Exemple #6
0
    internal static int probe_dtz_table(Position pos, int wdl, ref int success)
    {
        TBEntry ptr;
        ulong   idx;
        int     i;
        int     res;

        int[] p = new int[DefineConstants.TBPIECES];

        // Obtain the position's material signature key.
        ulong key = pos.material_key();

        if (GlobalMembersTbcore.DTZ_table[0].key1 != key && GlobalMembersTbcore.DTZ_table[0].key2 != key)
        {
            for (i = 1; i < DefineConstants.DTZ_ENTRIES; i++)
            {
                if (GlobalMembersTbcore.DTZ_table[i].key1 == key)
                {
                    break;
                }
            }
            if (i < DefineConstants.DTZ_ENTRIES)
            {
                DTZTableEntry table_entry = GlobalMembersTbcore.DTZ_table[i];
                for (; i > 0; i--)
                {
                    GlobalMembersTbcore.DTZ_table[i] = GlobalMembersTbcore.DTZ_table[i - 1];
                }
                GlobalMembersTbcore.DTZ_table[0] = table_entry;
            }
            else
            {
                TBHashEntry[] ptr2 = GlobalMembersTbcore.TB_hash[key >> (64 - DefineConstants.TBHASHBITS)];
                for (i = 0; i < DefineConstants.HSHMAX; i++)
                {
                    if (ptr2[i].key == key)
                    {
                        break;
                    }
                }
                if (i == DefineConstants.HSHMAX)
                {
                    success = 0;
                    return(0);
                }
                ptr = ptr2[i].ptr;
                string str    = new string(new char[16]);
                int    mirror = (ptr.key != key);
                GlobalMembersTbprobe.prt_str(pos, str, mirror);
                if (GlobalMembersTbcore.DTZ_table[DefineConstants.DTZ_ENTRIES - 1].entry != null)
                {
                    GlobalMembersTbcore.free_dtz_entry(GlobalMembersTbcore.DTZ_table[DefineConstants.DTZ_ENTRIES - 1].entry);
                }
                for (i = DefineConstants.DTZ_ENTRIES - 1; i > 0; i--)
                {
                    GlobalMembersTbcore.DTZ_table[i] = GlobalMembersTbcore.DTZ_table[i - 1];
                }
                GlobalMembersTbcore.load_dtz_table(ref str, GlobalMembersTbprobe.calc_key(pos, mirror), GlobalMembersTbprobe.calc_key(pos, mirror == 0));
            }
        }

        ptr = GlobalMembersTbcore.DTZ_table[0].entry;
        if (ptr == null)
        {
            success = 0;
            return(0);
        }

        int bside;
        int mirror;
        int cmirror;

        if (ptr.symmetric == 0)
        {
            if (key != ptr.key)
            {
                cmirror = 8;
                mirror  = 0x38;
                bside   = (pos.side_to_move() == Color.WHITE);
            }
            else
            {
                cmirror = mirror = 0;
                bside   = !(pos.side_to_move() == Color.WHITE);
            }
        }
        else
        {
            cmirror = (int)pos.side_to_move() == ((int)Color.WHITE) != 0 ? 0 : 8;
            mirror  = (int)pos.side_to_move() == ((int)Color.WHITE) != 0 ? 0 : 0x38;
            bside   = 0;
        }

        if (ptr.has_pawns == 0)
        {
            DTZEntry_piece entry = (DTZEntry_piece)ptr;
            if ((entry.flags & 1) != bside && entry.symmetric == 0)
            {
                success = -1;
                return(0);
            }
            byte[] pc = entry.pieces;
            for (i = 0; i < entry.num;)
            {
                uint GlobalMembersBitboard.long bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), (PieceType)(pc[i] & 0x07));
                do
                {
                    p[i++] = (int)GlobalMembersBitboard.pop_lsb(ref bb);
                } while (bb);
            }
            idx = GlobalMembersTbcore.encode_piece((TBEntry_piece)entry, entry.norm, p, entry.factor);
            res = GlobalMembersTbcore.decompress_pairs(entry.precomp, idx);

            if ((entry.flags & 2) != 0)
            {
                res = entry.map[entry.map_idx[GlobalMembersTbcore.wdl_to_map[wdl + 2]] + res];
            }

            if (!(entry.flags & GlobalMembersTbcore.pa_flags[wdl + 2]) || (wdl & 1))
            {
                res *= 2;
            }
        }
        else
        {
            DTZEntry_pawn entry = (DTZEntry_pawn)ptr;
            int           k     = entry.file[0].pieces[0] ^ cmirror;
            uint GlobalMembersBitboard.long bb = pos.pieces((Color)(k >> 3), (PieceType)(k & 0x07));
            i = 0;
            do
            {
                p[i++] = (int)GlobalMembersBitboard.pop_lsb(ref bb) ^ mirror;
            } while (bb);
            int f = GlobalMembersTbcore.pawn_file((TBEntry_pawn)entry, p);
            if ((entry.flags[f] & 1) != bside)
            {
                success = -1;
                return(0);
            }
            byte[] pc = entry.file[f].pieces;
            for (; i < entry.num;)
            {
                bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), (PieceType)(pc[i] & 0x07));
                do
                {
                    p[i++] = (int)GlobalMembersBitboard.pop_lsb(ref bb) ^ mirror;
                } while (bb);
            }
            idx = GlobalMembersTbcore.encode_pawn((TBEntry_pawn)entry, entry.file[f].norm, p, entry.file[f].factor);
            res = GlobalMembersTbcore.decompress_pairs(entry.file[f].precomp, idx);

            if ((entry.flags[f] & 2) != 0)
            {
                res = entry.map[entry.map_idx[f, GlobalMembersTbcore.wdl_to_map[wdl + 2]] + res];
            }

            if (!(entry.flags[f] & GlobalMembersTbcore.pa_flags[wdl + 2]) || (wdl & 1))
            {
                res *= 2;
            }
        }

        return(res);
    }
Exemple #7
0
    // probe_wdl_table and probe_dtz_table require similar adaptations.
    internal static int probe_wdl_table(Position pos, ref int success)
    {
        TBEntry ptr;

        TBHashEntry[] ptr2;
        ulong         idx;
        ulong         key;
        int           i;
        byte          res;

        int[] p = new int[DefineConstants.TBPIECES];

        // Obtain the position's material signature key.
        key = pos.material_key();

        // Test for KvK.
        if (key == (Zobrist.psq[(int)Color.WHITE][(int)PieceType.KING][0] ^ Zobrist.psq[(int)Color.BLACK][(int)PieceType.KING][0]))
        {
            return(0);
        }

        ptr2 = GlobalMembersTbcore.TB_hash[key >> (64 - DefineConstants.TBHASHBITS)];
        for (i = 0; i < DefineConstants.HSHMAX; i++)
        {
            if (ptr2[i].key == key)
            {
                break;
            }
        }
        if (i == DefineConstants.HSHMAX)
        {
            success = 0;
            return(0);
        }

        ptr = ptr2[i].ptr;
        if (ptr.ready == 0)
        {
            LOCK(GlobalMembersTbcore.TB_mutex);
            if (ptr.ready == 0)
            {
                string str = new string(new char[16]);
                GlobalMembersTbprobe.prt_str(pos, str, ptr.key != key);
                if (GlobalMembersTbcore.init_table_wdl(ptr, ref str) == 0)
                {
                    ptr2[i].key = 0UL;
                    success     = 0;
                    UNLOCK(GlobalMembersTbcore.TB_mutex);
                    return(0);
                }
                // Memory barrier to ensure ptr->ready = 1 is not reordered.
        #if _MSC_VER
                _ReadWriteBarrier();
        #else
                __asm__ __volatile__ = new __asm__("" global::: "memory");
        #endif
                ptr.ready = 1;
            }
            UNLOCK(GlobalMembersTbcore.TB_mutex);
        }

        int bside;
        int mirror;
        int cmirror;
        if (ptr.symmetric == 0)
        {
            if (key != ptr.key)
            {
                cmirror = 8;
                mirror  = 0x38;
                bside   = (pos.side_to_move() == Color.WHITE);
            }
            else
            {
                cmirror = mirror = 0;
                bside   = !(pos.side_to_move() == Color.WHITE);
            }
        }
        else
        {
            cmirror = (int)pos.side_to_move() == ((int)Color.WHITE) != 0 ? 0 : 8;
            mirror  = (int)pos.side_to_move() == ((int)Color.WHITE) != 0 ? 0 : 0x38;
            bside   = 0;
        }

        // p[i] is to contain the square 0-63 (A1-H8) for a piece of type
        // pc[i] ^ cmirror, where 1 = white pawn, ..., 14 = black king.
        // Pieces of the same type are guaranteed to be consecutive.
        if (ptr.has_pawns == 0)
        {
            TBEntry_piece entry = (TBEntry_piece)ptr;
            byte[]        pc    = entry.pieces[bside];
            for (i = 0; i < entry.num;)
            {
                uint GlobalMembersBitboard.long bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), (PieceType)(pc[i] & 0x07));
                do
                {
                    p[i++] = (int)GlobalMembersBitboard.pop_lsb(ref bb);
                } while (bb);
            }
            idx = GlobalMembersTbcore.encode_piece(entry, entry.norm[bside], p, entry.factor[bside]);
            res = GlobalMembersTbcore.decompress_pairs(entry.precomp[bside], idx);
        }
        else
        {
            TBEntry_pawn entry = (TBEntry_pawn)ptr;
            int          k     = entry.file[0].pieces[0, 0] ^ cmirror;
            uint GlobalMembersBitboard.long bb = pos.pieces((Color)(k >> 3), (PieceType)(k & 0x07));
            i = 0;
            do
            {
                p[i++] = (int)GlobalMembersBitboard.pop_lsb(ref bb) ^ mirror;
            } while (bb);
            int    f  = GlobalMembersTbcore.pawn_file(entry, p);
            byte[] pc = entry.file[f].pieces[bside];
            for (; i < entry.num;)
            {
                bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), (PieceType)(pc[i] & 0x07));
                do
                {
                    p[i++] = (int)GlobalMembersBitboard.pop_lsb(ref bb) ^ mirror;
                } while (bb);
            }
            idx = GlobalMembersTbcore.encode_pawn(entry, entry.file[f].norm[bside], p, entry.file[f].factor[bside]);
            res = GlobalMembersTbcore.decompress_pairs(entry.file[f].precomp[bside], idx);
        }

        return(((int)res) - 2);
    }
Exemple #8
0
    internal static byte decompress_pairs(PairsData d, ulong idx)
    {
        bool isLittleEndian = GlobalMembersTbprobe.is_little_endian();

        return(isLittleEndian ? GlobalMembersTbcore.decompress_pairs <true>(d, idx) : GlobalMembersTbcore.decompress_pairs <false>(d, idx));
    }