int MoleculeCIPCalculator::_cip_rules_cmp()

in core/indigo-core/molecule/src/molecule_cip_calculator.cpp [992:1776]


int MoleculeCIPCalculator::_cip_rules_cmp(int i1, int i2, void* context)
{
    int res = 0;
    QS_DEF(Array<CIPDesc>, cip);
    QS_DEF(Array<int>, used1);
    QS_DEF(Array<int>, used2);

    auto* cur_context = static_cast<CIPContext*>(context);
    BaseMolecule& mol = *(BaseMolecule*)cur_context->mol;
    cip.copy(*(Array<CIPDesc>*)cur_context->cip_desc);
    used1.copy(*(Array<int>*)cur_context->used1);
    used2.copy(*(Array<int>*)cur_context->used2);

    if ((i1 == -1) && (i2 == -1))
        return 0;

    if (i1 == -1)
        return 1;

    if (i2 == -1)
        return -1;

    if (mol.getAtomNumber(i1) > mol.getAtomNumber(i2))
        return -1;
    else if (mol.getAtomNumber(i1) < mol.getAtomNumber(i2))
        return 1;

    if (cur_context->isotope_check)
    {
        int m1 = mol.getAtomIsotope(i1) == 0 ? Element::getDefaultIsotope(mol.getAtomNumber(i1)) : mol.getAtomIsotope(i1);
        int m2 = mol.getAtomIsotope(i2) == 0 ? Element::getDefaultIsotope(mol.getAtomNumber(i2)) : mol.getAtomIsotope(i2);

        if (m1 > m2)
            return -1;
        else if (m1 < m2)
            return 1;
    }

    if (cur_context->use_rule_4)
    {
        if ((cip[i2] == CIPDesc::NONE) && (cip[i1] > CIPDesc::UNKNOWN))
            return -1;
        else if ((cip[i2] > CIPDesc::UNKNOWN) && (cip[i2] < CIPDesc::S) && (cip[i1] > CIPDesc::r))
            return -1;
        else if ((cip[i1] == CIPDesc::NONE) && (cip[i2] > CIPDesc::UNKNOWN))
            return 1;
        else if ((cip[i1] > CIPDesc::UNKNOWN) && (cip[i1] < CIPDesc::S) && (cip[i2] > CIPDesc::r))
            return 1;

        if ((cip[i1] > CIPDesc::r) && (cip[i2] > CIPDesc::r))
        {
            if ((cur_context->ref_cip1 != CIPDesc::NONE) && (cur_context->ref_cip2 != CIPDesc::NONE))
            {
                if ((cip[i1] == cur_context->ref_cip1) && (cip[i2] != cur_context->ref_cip2))
                    return -1;
                else if ((cip[i1] != cur_context->ref_cip1) && (cip[i2] == cur_context->ref_cip2))
                    return 1;
            }
            else
            {
                cur_context->ref_cip1 = cip[i1];
                cur_context->ref_cip2 = cip[i2];
            }
        }
        else if ((cip[i1] == CIPDesc::r) && (cip[i2] == CIPDesc::s))
            return -1;
        else if ((cip[i1] == CIPDesc::s) && (cip[i2] == CIPDesc::r))
            return 1;
    }

    if (cur_context->use_rule_5)
    {
        if ((cip[i1] == CIPDesc::R) && (cip[i2] == CIPDesc::S))
            return -1;
        else if ((cip[i1] == CIPDesc::S) && (cip[i2] == CIPDesc::R))
            return 1;
    }

    const Vertex& v1 = mol.getVertex(i1);
    QS_DEF(Array<int>, neibs1);
    QS_DEF(Array<int>, cip_neibs1);
    neibs1.clear();
    cip_neibs1.clear();
    for (auto i : v1.neighbors())
    {
        if (used1.find(v1.neiVertex(i)) == -1)
        {
            neibs1.push(v1.neiVertex(i));
        }
    }
    if (neibs1.size() > 1)
    {
        QS_DEF(CIPContext, next_context);
        QS_DEF(Array<int>, used1_next);
        QS_DEF(Array<int>, used2_next);
        used1_next.copy(used1);
        used1_next.push(i1);
        used2_next.copy(used1_next);
        next_context.mol = &mol;
        next_context.cip_desc = &cip;
        next_context.used1 = &used1_next;
        next_context.used2 = &used2_next;
        next_context.next_level = false;
        next_context.isotope_check = cur_context->isotope_check;
        next_context.use_stereo = cur_context->use_stereo;
        next_context.use_rule_4 = cur_context->use_rule_4;
        next_context.ref_cip1 = cur_context->ref_cip1;
        next_context.ref_cip2 = cur_context->ref_cip2;
        next_context.use_rule_5 = cur_context->use_rule_5;
        cipSort(neibs1, &next_context);
    }

    cip_neibs1.copy(neibs1);

    if (mol.vertexInRing(i1))
    {
        for (auto i : v1.neighbors())
        {
            if ((used1.find(v1.neiVertex(i)) != -1) && (used1.find(v1.neiVertex(i)) != (used1.size() - 1)))
            {
                int at_idx = v1.neiVertex(i);
                int an = mol.getAtomNumber(at_idx);
                bool inserted = false;

                if (cip_neibs1.size() > 0)
                {
                    for (int j = 0; j < cip_neibs1.size(); j++)
                    {
                        if (mol.getAtomNumber(cip_neibs1[j]) < an)
                        {
                            cip_neibs1.expand(cip_neibs1.size() + 1);
                            for (auto k = cip_neibs1.size() - 1; k > j; k--)
                            {
                                cip_neibs1[k] = cip_neibs1[k - 1];
                            }
                            cip_neibs1[j] = at_idx;
                            inserted = true;
                            break;
                        }
                    }
                    if (!inserted)
                    {
                        cip_neibs1.push(at_idx);
                    }
                }
                else
                {
                    cip_neibs1.push(at_idx);
                }
            }
        }
    }

    for (auto i : v1.neighbors())
    {
        if (mol.getBondOrder(v1.neiEdge(i)) == BOND_SINGLE)
        {
        }
        else if (mol.getBondOrder(v1.neiEdge(i)) == BOND_DOUBLE)
        {
            int ins = cip_neibs1.find(v1.neiVertex(i));
            if (ins > -1)
            {
                cip_neibs1.expand(cip_neibs1.size() + 1);
                if (ins < cip_neibs1.size() - 2)
                {
                    for (auto k = cip_neibs1.size() - 1; k > ins; k--)
                    {
                        cip_neibs1[k] = cip_neibs1[k - 1];
                    }
                }
                cip_neibs1[ins + 1] = v1.neiVertex(i);
            }
            else if ((used1.find(v1.neiVertex(i)) != -1) && (used1.find(v1.neiVertex(i)) == (used1.size() - 1)))
            {
                int at_idx = v1.neiVertex(i);
                int an = mol.getAtomNumber(at_idx);
                bool inserted = false;

                if (cip_neibs1.size() > 0)
                {
                    for (int j = 0; j < cip_neibs1.size(); j++)
                    {
                        if (mol.getAtomNumber(cip_neibs1[j]) < an)
                        {
                            cip_neibs1.expand(cip_neibs1.size() + 1);
                            for (auto k = cip_neibs1.size() - 1; k > j; k--)
                            {
                                cip_neibs1[k] = cip_neibs1[k - 1];
                            }
                            cip_neibs1[j] = at_idx;
                            inserted = true;
                            break;
                        }
                    }
                    if (!inserted)
                    {
                        cip_neibs1.push(at_idx);
                    }
                }
                else
                {
                    cip_neibs1.push(at_idx);
                }
            }
        }
        else if (mol.getBondOrder(v1.neiEdge(i)) == BOND_TRIPLE)
        {
            int ins = cip_neibs1.find(v1.neiVertex(i));
            if (ins > -1)
            {
                cip_neibs1.expand(cip_neibs1.size() + 2);
                if (ins < cip_neibs1.size() - 3)
                {
                    for (auto k = cip_neibs1.size() - 1; k > ins; k--)
                    {
                        cip_neibs1[k] = cip_neibs1[k - 2];
                    }
                }
                cip_neibs1[ins + 1] = v1.neiVertex(i);
                cip_neibs1[ins + 2] = v1.neiVertex(i);
            }
            else if ((used1.find(v1.neiVertex(i)) != -1) && (used1.find(v1.neiVertex(i)) == (used1.size() - 1)))
            {
                int at_idx = v1.neiVertex(i);
                int an = mol.getAtomNumber(at_idx);
                bool inserted = false;

                if (cip_neibs1.size() > 0)
                {
                    for (int j = 0; j < cip_neibs1.size(); j++)
                    {
                        if (mol.getAtomNumber(cip_neibs1[j]) < an)
                        {
                            cip_neibs1.expand(cip_neibs1.size() + 2);
                            for (auto k = cip_neibs1.size() - 1; k > j; k--)
                            {
                                cip_neibs1[k] = cip_neibs1[k - 1];
                                cip_neibs1[k - 1] = cip_neibs1[k - 2];
                            }
                            cip_neibs1[j] = at_idx;
                            cip_neibs1[j + 1] = at_idx;
                            inserted = true;
                            break;
                        }
                    }
                    if (!inserted)
                    {
                        cip_neibs1.push(at_idx);
                        cip_neibs1.push(at_idx);
                    }
                }
                else
                {
                    cip_neibs1.push(at_idx);
                    cip_neibs1.push(at_idx);
                }
            }
        }
        else if (mol.getBondOrder(v1.neiEdge(i)) == BOND_AROMATIC)
        {
        }
    }

    const Vertex& v2 = mol.getVertex(i2);
    QS_DEF(Array<int>, neibs2);
    QS_DEF(Array<int>, cip_neibs2);
    neibs2.clear();
    cip_neibs2.clear();

    for (auto i : v2.neighbors())
    {
        if (used2.find(v2.neiVertex(i)) == -1)
        {
            neibs2.push(v2.neiVertex(i));
        }
    }
    if (neibs2.size() > 1)
    {
        QS_DEF(CIPContext, next_context);
        QS_DEF(Array<int>, used1_next);
        QS_DEF(Array<int>, used2_next);
        used1_next.copy(used2);
        used1_next.push(i2);
        used2_next.copy(used1_next);
        next_context.mol = &mol;
        next_context.cip_desc = &cip;
        next_context.used1 = &used1_next;
        next_context.used2 = &used2_next;
        next_context.next_level = false;
        next_context.isotope_check = cur_context->isotope_check;
        next_context.use_stereo = cur_context->use_stereo;
        next_context.use_rule_4 = cur_context->use_rule_4;
        next_context.ref_cip1 = cur_context->ref_cip1;
        next_context.ref_cip2 = cur_context->ref_cip2;
        next_context.use_rule_5 = cur_context->use_rule_5;
        cipSort(neibs2, &next_context);
    }

    cip_neibs2.copy(neibs2);

    if (mol.vertexInRing(i2))
    {
        for (auto i : v2.neighbors())
        {
            if ((used2.find(v2.neiVertex(i)) != -1) && (used2.find(v2.neiVertex(i)) != (used2.size() - 1)))
            {
                int at_idx = v2.neiVertex(i);
                int an = mol.getAtomNumber(at_idx);
                bool inserted = false;

                if (cip_neibs2.size() > 0)
                {
                    for (int j = 0; j < cip_neibs2.size(); j++)
                    {
                        if (mol.getAtomNumber(cip_neibs2[j]) < an)
                        {
                            cip_neibs2.expand(cip_neibs2.size() + 1);
                            for (auto k = cip_neibs2.size() - 1; k > j; k--)
                            {
                                cip_neibs2[k] = cip_neibs2[k - 1];
                            }
                            cip_neibs2[j] = at_idx;
                            inserted = true;
                            break;
                        }
                    }
                    if (!inserted)
                    {
                        cip_neibs2.push(at_idx);
                    }
                }
                else
                {
                    cip_neibs2.push(at_idx);
                }
            }
        }
    }

    for (auto i : v2.neighbors())
    {
        if (mol.getBondOrder(v2.neiEdge(i)) == BOND_SINGLE)
        {
        }
        else if (mol.getBondOrder(v2.neiEdge(i)) == BOND_DOUBLE)
        {
            int ins = cip_neibs2.find(v2.neiVertex(i));
            if (ins > -1)
            {
                cip_neibs2.expand(cip_neibs2.size() + 1);
                if (ins < cip_neibs2.size() - 2)
                {
                    for (auto k = cip_neibs2.size() - 1; k > ins; k--)
                    {
                        cip_neibs2[k] = cip_neibs2[k - 1];
                    }
                }
                cip_neibs2[ins + 1] = v2.neiVertex(i);
            }
            else if ((used2.find(v2.neiVertex(i)) != -1) && (used2.find(v2.neiVertex(i)) == (used2.size() - 1)))
            {
                int at_idx = v2.neiVertex(i);
                int an = mol.getAtomNumber(at_idx);
                bool inserted = false;

                if (cip_neibs2.size() > 0)
                {
                    for (int j = 0; j < cip_neibs2.size(); j++)
                    {
                        if (mol.getAtomNumber(cip_neibs2[j]) < an)
                        {
                            cip_neibs2.expand(cip_neibs2.size() + 1);
                            for (auto k = cip_neibs2.size() - 1; k > j; k--)
                            {
                                cip_neibs2[k] = cip_neibs2[k - 1];
                            }
                            cip_neibs2[j] = at_idx;
                            inserted = true;
                            break;
                        }
                    }
                    if (!inserted)
                    {
                        cip_neibs2.push(at_idx);
                    }
                }
                else
                {
                    cip_neibs2.push(at_idx);
                }
            }
        }
        else if (mol.getBondOrder(v2.neiEdge(i)) == BOND_TRIPLE)
        {
            int ins = cip_neibs2.find(v2.neiVertex(i));
            if (ins > -1)
            {
                cip_neibs2.expand(cip_neibs2.size() + 2);
                if (ins < cip_neibs2.size() - 3)
                {
                    for (auto k = cip_neibs2.size() - 1; k > ins; k--)
                    {
                        cip_neibs2[k] = cip_neibs2[k - 2];
                    }
                }
                cip_neibs2[ins + 1] = v2.neiVertex(i);
                cip_neibs2[ins + 2] = v2.neiVertex(i);
            }
            else if ((used2.find(v2.neiVertex(i)) != -1) && (used2.find(v2.neiVertex(i)) == (used2.size() - 1)))
            {
                int at_idx = v2.neiVertex(i);
                int an = mol.getAtomNumber(at_idx);
                bool inserted = false;

                if (cip_neibs2.size() > 0)
                {
                    for (int j = 0; j < cip_neibs2.size(); j++)
                    {
                        if (mol.getAtomNumber(cip_neibs2[j]) < an)
                        {
                            cip_neibs2.expand(cip_neibs2.size() + 2);
                            for (auto k = cip_neibs2.size() - 1; k > j; k--)
                            {
                                cip_neibs2[k] = cip_neibs2[k - 1];
                                cip_neibs2[k - 1] = cip_neibs2[k - 2];
                            }
                            cip_neibs2[j] = at_idx;
                            cip_neibs2[j + 1] = at_idx;
                            inserted = true;
                            break;
                        }
                    }
                    if (!inserted)
                    {
                        cip_neibs2.push(at_idx);
                        cip_neibs2.push(at_idx);
                    }
                }
                else
                {
                    cip_neibs2.push(at_idx);
                    cip_neibs2.push(at_idx);
                }
            }
        }
        else if (mol.getBondOrder(v2.neiEdge(i)) == BOND_AROMATIC)
        {
        }
    }

    if (cip_neibs2.size() > cip_neibs1.size())
    {
        for (auto i = 0; i < cip_neibs1.size(); i++)
        {
            res = mol.getAtomNumber(cip_neibs2[i]) - mol.getAtomNumber(cip_neibs1[i]);
            if (res > 0)
                return 1;
            else if (res < 0)
                return -1;
        }
        return 1;
    }
    else if (cip_neibs2.size() < cip_neibs1.size())
    {
        for (auto i = 0; i < cip_neibs2.size(); i++)
        {
            res = mol.getAtomNumber(cip_neibs2[i]) - mol.getAtomNumber(cip_neibs1[i]);
            if (res > 0)
                return 1;
            else if (res < 0)
                return -1;
        }
        return -1;
    }
    else if (cip_neibs1.size() > 0)
    {
        for (auto i = 0; i < cip_neibs1.size(); i++)
        {
            res = mol.getAtomNumber(cip_neibs2[i]) - mol.getAtomNumber(cip_neibs1[i]);
            if (res > 0)
                return 1;
            else if (res < 0)
                return -1;
        }

        if (cur_context->isotope_check)
        {
            for (auto i = 0; i < neibs1.size(); i++)
            {
                int m1 = mol.getAtomIsotope(neibs1[i]) == 0 ? Element::getDefaultIsotope(mol.getAtomNumber(neibs1[i])) : mol.getAtomIsotope(neibs1[i]);
                int m2 = mol.getAtomIsotope(neibs2[i]) == 0 ? Element::getDefaultIsotope(mol.getAtomNumber(neibs2[i])) : mol.getAtomIsotope(neibs2[i]);

                if (m1 > m2)
                    return -1;
                else if (m1 < m2)
                    return 1;
            }
        }

        if (cur_context->use_rule_4)
        {
            for (auto i = 0; i < neibs1.size(); i++)
            {
                if ((cip[neibs2[i]] == CIPDesc::NONE) && (cip[neibs1[i]] > CIPDesc::UNKNOWN))
                    return -1;
                else if ((cip[neibs2[i]] > CIPDesc::UNKNOWN) && (cip[neibs2[i]] < CIPDesc::S) && (cip[neibs1[i]] > CIPDesc::r))
                    return -1;
                else if ((cip[neibs1[i]] == CIPDesc::NONE) && (cip[neibs2[i]] > CIPDesc::UNKNOWN))
                    return 1;
                else if ((cip[neibs1[i]] > CIPDesc::UNKNOWN) && (cip[neibs1[i]] < CIPDesc::S) && (cip[neibs2[i]] > CIPDesc::r))
                    return 1;

                if ((cip[neibs1[i]] > CIPDesc::r) && (cip[neibs2[i]] > CIPDesc::r))
                {
                    if ((cur_context->ref_cip1 != CIPDesc::NONE) && (cur_context->ref_cip2 != CIPDesc::NONE))
                    {
                        if ((cip[neibs1[i]] == cur_context->ref_cip1) && (cip[neibs2[i]] != cur_context->ref_cip2))
                            return -1;
                        else if ((cip[neibs1[i]] != cur_context->ref_cip1) && (cip[neibs2[i]] == cur_context->ref_cip2))
                            return 1;
                    }
                    else
                    {
                        cur_context->ref_cip1 = cip[neibs1[i]];
                        cur_context->ref_cip2 = cip[neibs2[i]];
                    }
                }
                else if ((cip[neibs1[i]] == CIPDesc::r) && (cip[neibs2[i]] == CIPDesc::s))
                    return -1;
                else if ((cip[neibs1[i]] == CIPDesc::s) && (cip[neibs2[i]] == CIPDesc::r))
                    return 1;
            }
        }

        if (cur_context->use_rule_5)
        {
            for (auto i = 0; i < neibs1.size(); i++)
            {
                if ((cip[neibs1[i]] == CIPDesc::R) && (cip[neibs2[i]] == CIPDesc::S))
                    return -1;
                else if ((cip[neibs1[i]] == CIPDesc::S) && (cip[neibs2[i]] == CIPDesc::R))
                    return 1;
            }
        }

        if (!cur_context->next_level)
            return 0;

        int next_level_branches = neibs2.size() > neibs1.size() ? neibs2.size() : neibs1.size();

        if (next_level_branches > 0)
        {
            for (auto i = 0; i < next_level_branches; i++)
            {
                QS_DEF(CIPContext, next_context);
                QS_DEF(Array<int>, used1_next);
                QS_DEF(Array<int>, used2_next);
                used1_next.copy(used1);
                used1_next.push(i1);
                used2_next.copy(used2);
                used2_next.push(i2);
                next_context.mol = &mol;
                next_context.cip_desc = &cip;
                next_context.used1 = &used1_next;
                next_context.used2 = &used2_next;
                next_context.next_level = false;
                next_context.isotope_check = cur_context->isotope_check;
                next_context.use_stereo = cur_context->use_stereo;
                next_context.use_rule_4 = cur_context->use_rule_4;
                next_context.ref_cip1 = cur_context->ref_cip1;
                next_context.ref_cip2 = cur_context->ref_cip2;
                next_context.use_rule_5 = cur_context->use_rule_5;
                res = _cip_rules_cmp(neibs1[i], neibs2[i], &next_context);
                if (res > 0)
                    return 1;
                else if (res < 0)
                    return -1;
            }

            for (auto i = 0; i < next_level_branches; i++)
            {
                QS_DEF(CIPContext, next_context);
                QS_DEF(Array<int>, used1_next);
                QS_DEF(Array<int>, used2_next);
                used1_next.copy(used1);
                used1_next.push(i1);
                used2_next.copy(used2);
                used2_next.push(i2);
                next_context.mol = &mol;
                next_context.cip_desc = &cip;
                next_context.used1 = &used1_next;
                next_context.used2 = &used2_next;
                next_context.next_level = true;
                next_context.isotope_check = cur_context->isotope_check;
                next_context.use_stereo = cur_context->use_stereo;
                next_context.use_rule_4 = cur_context->use_rule_4;
                next_context.ref_cip1 = cur_context->ref_cip1;
                next_context.ref_cip2 = cur_context->ref_cip2;
                next_context.use_rule_5 = cur_context->use_rule_5;
                res = _cip_rules_cmp(neibs1[i], neibs2[i], &next_context);
                if (res > 0)
                    return 1;
                else if (res < 0)
                    return -1;
            }
        }
        else if (neibs2.size() > 0)
            return 1;
        else if (neibs1.size() > 0)
            return -1;
    }

    if (used1.size() == 1 && !cur_context->isotope_check)
    {
        int isotope_found = 0;
        for (auto i = mol.vertexBegin(); i != mol.vertexEnd(); i = mol.vertexNext(i))
        {
            if (mol.getAtomIsotope(i) > 0)
            {
                isotope_found = mol.getAtomIsotope(i);
            }
        }
        if (isotope_found > 0)
        {
            QS_DEF(CIPContext, next_context);
            QS_DEF(Array<int>, used1_next);
            QS_DEF(Array<int>, used2_next);
            used1_next.copy(used1);
            used2_next.copy(used2);
            next_context.mol = &mol;
            next_context.cip_desc = &cip;
            next_context.used1 = &used1_next;
            next_context.used2 = &used2_next;
            next_context.next_level = false;
            next_context.isotope_check = true;
            next_context.use_stereo = cur_context->use_stereo;
            next_context.use_rule_4 = cur_context->use_rule_4;
            next_context.ref_cip1 = cur_context->ref_cip1;
            next_context.ref_cip2 = cur_context->ref_cip2;
            next_context.use_rule_5 = cur_context->use_rule_5;
            res = _cip_rules_cmp(i1, i2, &next_context);
            if (res > 0)
                return 1;
            else if (res < 0)
                return -1;
        }

        if (isotope_found > 0)
        {
            QS_DEF(CIPContext, next_context);
            QS_DEF(Array<int>, used1_next);
            QS_DEF(Array<int>, used2_next);
            used1_next.copy(used1);
            used2_next.copy(used2);
            next_context.mol = &mol;
            next_context.cip_desc = &cip;
            next_context.used1 = &used1_next;
            next_context.used2 = &used2_next;
            next_context.next_level = true;
            next_context.isotope_check = true;
            next_context.use_stereo = cur_context->use_stereo;
            next_context.use_rule_4 = cur_context->use_rule_4;
            next_context.ref_cip1 = cur_context->ref_cip1;
            next_context.ref_cip2 = cur_context->ref_cip2;
            next_context.use_rule_5 = cur_context->use_rule_5;
            res = _cip_rules_cmp(i1, i2, &next_context);
            if (res > 0)
                return 1;
            else if (res < 0)
                return -1;
        }
    }

    if (used1.size() == 1 && cur_context->use_stereo && !cur_context->use_rule_4)
    {
        if (_getNumberOfStereoDescritors(cip) > 0)
        {
            QS_DEF(CIPContext, next_context);
            QS_DEF(Array<int>, used1_next);
            QS_DEF(Array<int>, used2_next);
            used1_next.copy(used1);
            used2_next.copy(used2);
            next_context.mol = &mol;
            next_context.cip_desc = &cip;
            next_context.used1 = &used1_next;
            next_context.used2 = &used2_next;
            next_context.next_level = false;
            next_context.isotope_check = true;
            next_context.use_stereo = cur_context->use_stereo;
            next_context.use_rule_4 = true;
            next_context.ref_cip1 = CIPDesc::NONE;
            next_context.ref_cip2 = CIPDesc::NONE;
            next_context.use_rule_5 = false;
            cur_context->use_rule_4 = true;
            res = _cip_rules_cmp(i1, i2, &next_context);
            if (res > 0)
                return 1;
            else if (res < 0)
                return -1;
        }
        if (_getNumberOfStereoDescritors(cip) > 0)
        {
            QS_DEF(CIPContext, next_context);
            QS_DEF(Array<int>, used1_next);
            QS_DEF(Array<int>, used2_next);
            used1_next.copy(used1);
            used2_next.copy(used2);
            next_context.mol = &mol;
            next_context.cip_desc = &cip;
            next_context.used1 = &used1_next;
            next_context.used2 = &used2_next;
            next_context.next_level = true;
            next_context.isotope_check = true;
            next_context.use_stereo = cur_context->use_stereo;
            next_context.use_rule_4 = true;
            next_context.ref_cip1 = CIPDesc::NONE;
            next_context.ref_cip2 = CIPDesc::NONE;
            next_context.use_rule_5 = false;
            cur_context->use_rule_4 = true;
            res = _cip_rules_cmp(i1, i2, &next_context);
            if (res > 0)
                return 1;
            else if (res < 0)
                return -1;
        }
    }

    if (used1.size() == 1 && cur_context->use_stereo && !cur_context->use_rule_5)
    {
        if (_getNumberOfStereoDescritors(cip) > 0)
        {
            QS_DEF(CIPContext, next_context);
            QS_DEF(Array<int>, used1_next);
            QS_DEF(Array<int>, used2_next);
            used1_next.copy(used1);
            used2_next.copy(used2);
            next_context.mol = &mol;
            next_context.cip_desc = &cip;
            next_context.used1 = &used1_next;
            next_context.used2 = &used2_next;
            next_context.next_level = false;
            next_context.isotope_check = true;
            next_context.use_stereo = cur_context->use_stereo;
            next_context.use_rule_4 = true;
            next_context.ref_cip1 = cip[i1];
            next_context.ref_cip2 = cip[i2];
            next_context.use_rule_5 = true;
            cur_context->use_rule_5 = true;
            res = _cip_rules_cmp(i1, i2, &next_context);
            if (res > 0)
                return 1;
            else if (res < 0)
                return -1;
        }

        if (_getNumberOfStereoDescritors(cip) > 0)
        {
            QS_DEF(CIPContext, next_context);
            QS_DEF(Array<int>, used1_next);
            QS_DEF(Array<int>, used2_next);
            used1_next.copy(used1);
            used2_next.copy(used2);
            next_context.mol = &mol;
            next_context.cip_desc = &cip;
            next_context.used1 = &used1_next;
            next_context.used2 = &used2_next;
            next_context.next_level = true;
            next_context.isotope_check = true;
            next_context.use_stereo = cur_context->use_stereo;
            next_context.use_rule_4 = true;
            next_context.ref_cip1 = cip[i1];
            next_context.ref_cip2 = cip[i2];
            next_context.use_rule_5 = true;
            cur_context->use_rule_5 = true;
            res = _cip_rules_cmp(i1, i2, &next_context);
            if (res > 0)
                return 1;
            else if (res < 0)
                return -1;
        }
    }

    return res;
}