third_party/inchi/INCHI_BASE/src/ichicans.c
int RemoveKnownNonStereoCenterParities( CANON_GLOBALS *pCG,
                                        sp_ATOM       *at,
                                        int           num_atoms,
                                        const AT_RANK *nCanonRank,
                                        const AT_RANK *nRank,
                                        CANON_STAT    *pCS )
{
    int i, j, n, m, k, num_neigh, ret = 0;
    /*AT_RANK nAtomRank;*/
    AT_RANK nNeighRank[MAX_NUM_STEREO_ATOM_NEIGH], nNeighOrd[MAX_NUM_STEREO_ATOM_NEIGH];
    AT_RANK *nVisited = NULL;

    for (i = 0; i < num_atoms; i++)
    {
        if (!at[i].parity || at[i].stereo_bond_neighbor[0])
        {
            continue;
        }
        if (!PARITY_CALCULATE( at[i].stereo_atom_parity ) && PARITY_WELL_DEF( at[i].stereo_atom_parity ))
        {
            continue;
        }
        num_neigh = at[i].valence;
        for (j = 0; j < num_neigh; j++)
        {
            nNeighRank[j] = nRank[(int) at[i].neighbor[j]];
            nNeighOrd[j] = j;
        }
        /*nAtomRank = nRank[i];*/
        if (num_neigh == 1)
        {
            continue;
        }
        pCG->m_pn_RankForSort = nNeighRank;
        insertions_sort( pCG, nNeighOrd, num_neigh, sizeof( nNeighRank[0] ), CompRanksOrd );
        for (j = k = 1; k && j < num_neigh; j++)
        {
            if (at[i].nRingSystem != at[(int) at[i].neighbor[(int) nNeighOrd[j]]].nRingSystem &&
                 /*  no more ring system membership check is necessary because */
                 /*  the two neighbors are to be constitutionally equivalent atoms: */
                nNeighRank[nNeighOrd[j - 1]] == nNeighRank[nNeighOrd[j]])
            {
                k = j;
                do
                {
                    if (!nVisited && !( nVisited = (AT_RANK*) inchi_malloc( sizeof( nVisited[0] )*num_atoms ) ))
                    {
                        ret = CT_OUT_OF_RAM;  /*   <BRKPT> */
                        goto exit_function;
                    }
                    memset( nVisited, 0, sizeof( nVisited[0] )*num_atoms );
                    nVisited[i] = 1;
                    if (PathsHaveIdenticalKnownParities( at, (AT_RANK) i, at[i].neighbor[(int) nNeighOrd[j - 1]],
                        (AT_RANK) i, at[i].neighbor[(int) nNeighOrd[k]],
                        nVisited, nVisited, nRank, nCanonRank, 1 ))
                    {
                        at[i].parity = 0; /*  remove parity */
                        at[i].stereo_atom_parity = 0;
                        at[i].final_parity = 0;
                        /* at[i].bHasStereoOrEquToStereo = 0; */
                        for (n = 0, m = pCS->nLenLinearCTStereoCarb - 1; n <= m; n++)
                        {
                            if (pCS->LinearCTStereoCarb[n].at_num == nCanonRank[i])
                            {
                                if (n < m)
                                {    /*  remove pCS->LinearCTStereoCarb[n] */
                                    memmove( pCS->LinearCTStereoCarb + n,
                                             pCS->LinearCTStereoCarb + n + 1,
                                             ( m - n ) * sizeof( pCS->LinearCTStereoCarb[0] ) );
                                }
                                pCS->nLenLinearCTStereoCarb--;
                                k = 0;

#if ( bRELEASE_VERSION == 0 )
                                pCS->bExtract |= EXTR_KNOWN_USED_TO_REMOVE_PARITY;
#endif

                                break;
                            }
                        }
                        if (k)
                        {
                            ret = CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
                            goto exit_function;
                        }
                        ret++;
                        break;
                    }
                }
                while (++k < num_neigh && nNeighRank[nNeighOrd[j - 1]] == nNeighRank[nNeighOrd[k]]);
            }
        }
    }

exit_function:
    if (nVisited)
    {
        inchi_free( nVisited );
    }

    return ret;
}
/****************************************************************************
 DFS along paths starting from the stereocenter through pairs of cut-edges
****************************************************************************/
DFS along paths starting from the stereocenter through pairs of cut-edges
DFS along paths starting from the stereocenter through pairs of cut - edges
int RemoveKnownNonStereoCenterParities( CANON_GLOBALS *pCG,
                                        sp_ATOM       *at,
                                        int           num_atoms,
                                        const AT_RANK *nCanonRank,
                                        const AT_RANK *nRank,
                                        CANON_STAT    *pCS )
{
    int i, j, n, m, k, num_neigh, ret = 0;
    AT_RANK nNeighRank[MAX_NUM_STEREO_ATOM_NEIGH], nNeighOrd[MAX_NUM_STEREO_ATOM_NEIGH];
    AT_RANK *nVisited = NULL;
    for (i = 0; i < num_atoms; i++)
    {
        if (!at[i].parity || at[i].stereo_bond_neighbor[0])
        {
            continue;
        }
        if (!PARITY_CALCULATE( at[i].stereo_atom_parity ) && PARITY_WELL_DEF( at[i].stereo_atom_parity ))
        {
            continue;
        }
        num_neigh = at[i].valence;
        for (j = 0; j < num_neigh; j++)
        {
            nNeighRank[j] = nRank[(int) at[i].neighbor[j]];
            nNeighOrd[j] = j;
        }
        if (num_neigh == 1)
        {
            continue;
        }
        pCG->m_pn_RankForSort = nNeighRank;
        insertions_sort( pCG, nNeighOrd, num_neigh, sizeof( nNeighRank[0] ), CompRanksOrd );
        for (j = k = 1; k && j < num_neigh; j++)
        {
            if (at[i].nRingSystem != at[(int) at[i].neighbor[(int) nNeighOrd[j]]].nRingSystem &&
                nNeighRank[nNeighOrd[j - 1]] == nNeighRank[nNeighOrd[j]])
            {
                k = j;
                do
                {
                    if (!nVisited && !( nVisited = (AT_RANK*) inchi_malloc( sizeof( nVisited[0] )*num_atoms ) ))
                    {
                        ret = CT_OUT_OF_RAM;  
                        goto exit_function;
                    }
                    memset( nVisited, 0, sizeof( nVisited[0] )*num_atoms );
                    nVisited[i] = 1;
                    if (PathsHaveIdenticalKnownParities( at, (AT_RANK) i, at[i].neighbor[(int) nNeighOrd[j - 1]],
                        (AT_RANK) i, at[i].neighbor[(int) nNeighOrd[k]],
                        nVisited, nVisited, nRank, nCanonRank, 1 ))
                    {
                        at[i].parity = 0; 
                        at[i].stereo_atom_parity = 0;
                        at[i].final_parity = 0;
                        for (n = 0, m = pCS->nLenLinearCTStereoCarb - 1; n <= m; n++)
                        {
                            if (pCS->LinearCTStereoCarb[n].at_num == nCanonRank[i])
                            {
                                if (n < m)
                                {    
                                    memmove( pCS->LinearCTStereoCarb + n,
                                             pCS->LinearCTStereoCarb + n + 1,
                                             ( m - n ) * sizeof( pCS->LinearCTStereoCarb[0] ) );
                                }
                                pCS->nLenLinearCTStereoCarb--;
                                k = 0;
#if ( bRELEASE_VERSION == 0 )
                                pCS->bExtract |= EXTR_KNOWN_USED_TO_REMOVE_PARITY;
#endif
                                break;
                            }
                        }
                        if (k)
                        {
                            ret = CT_STEREOCOUNT_ERR;  
                            goto exit_function;
                        }
                        ret++;
                        break;
                    }
                }
                while (++k < num_neigh && nNeighRank[nNeighOrd[j - 1]] == nNeighRank[nNeighOrd[k]]);
            }
        }
    }
exit_function:
    if (nVisited)
    {
        inchi_free( nVisited );
    }
    return ret;
}
int RemoveKnownNonStereoCenterParities ( CANON_GLOBALS * pCG , sp_ATOM * at , int num_atoms , const AT_RANK * nCanonRank , const AT_RANK * nRank , CANON_STAT * pCS ) { int i , j , n , m , k , num_neigh , ret = 0 ; AT_RANK nNeighRank [ MAX_NUM_STEREO_ATOM_NEIGH ] , nNeighOrd [ MAX_NUM_STEREO_ATOM_NEIGH ] ; AT_RANK * nVisited = NULL ; for ( i = 0 ; i < num_atoms ; i ++ ) { if ( ! at [ i ] . parity || at [ i ] . stereo_bond_neighbor [ 0 ] ) { continue ; } if ( ! PARITY_CALCULATE ( at [ i ] . stereo_atom_parity ) && PARITY_WELL_DEF ( at [ i ] . stereo_atom_parity ) ) { continue ; } num_neigh = at [ i ] . valence ; for ( j = 0 ; j < num_neigh ; j ++ ) { nNeighRank [ j ] = nRank [ ( int ) at [ i ] . neighbor [ j ] ] ; nNeighOrd [ j ] = j ; } if ( num_neigh == 1 ) { continue ; } pCG -> m_pn_RankForSort = nNeighRank ; insertions_sort ( pCG , nNeighOrd , num_neigh , sizeof ( nNeighRank [ 0 ] ) , CompRanksOrd ) ; for ( j = k = 1 ; k && j < num_neigh ; j ++ ) { if ( at [ i ] . nRingSystem != at [ ( int ) at [ i ] . neighbor [ ( int ) nNeighOrd [ j ] ] ] . nRingSystem && nNeighRank [ nNeighOrd [ j - 1 ] ] == nNeighRank [ nNeighOrd [ j ] ] ) { k = j ; do { if ( ! nVisited && ! ( nVisited = ( AT_RANK * ) inchi_malloc ( sizeof ( nVisited [ 0 ] ) * num_atoms ) ) ) { ret = CT_OUT_OF_RAM ; goto exit_function ; } memset ( nVisited , 0 , sizeof ( nVisited [ 0 ] ) * num_atoms ) ; nVisited [ i ] = 1 ; if ( PathsHaveIdenticalKnownParities ( at , ( AT_RANK ) i , at [ i ] . neighbor [ ( int ) nNeighOrd [ j - 1 ] ] , ( AT_RANK ) i , at [ i ] . neighbor [ ( int ) nNeighOrd [ k ] ] , nVisited , nVisited , nRank , nCanonRank , 1 ) ) { at [ i ] . parity = 0 ; at [ i ] . stereo_atom_parity = 0 ; at [ i ] . final_parity = 0 ; for ( n = 0 , m = pCS -> nLenLinearCTStereoCarb - 1 ; n <= m ; n ++ ) { if ( pCS -> LinearCTStereoCarb [ n ] . at_num == nCanonRank [ i ] ) { if ( n < m ) { memmove ( pCS -> LinearCTStereoCarb + n , pCS -> LinearCTStereoCarb + n + 1 , ( m - n ) * sizeof ( pCS -> LinearCTStereoCarb [ 0 ] ) ) ; } pCS -> nLenLinearCTStereoCarb -- ; k = 0 ; #if ( bRELEASE_VERSION == 0 ) pCS -> bExtract |= EXTR_KNOWN_USED_TO_REMOVE_PARITY ; #endif break ; } } if ( k ) { ret = CT_STEREOCOUNT_ERR ; goto exit_function ; } ret ++ ; break ; } } while ( ++ k < num_neigh && nNeighRank [ nNeighOrd [ j - 1 ] ] == nNeighRank [ nNeighOrd [ k ] ] ) ; } } } exit_function : if ( nVisited ) { inchi_free ( nVisited ) ; } return ret ; }
DFS along paths starting from the stereocenter through pairs of cut-edges
DFS along paths starting from the stereocenter through pairs of cut - edges
/*AT_RANK nAtomRank;*/ /*nAtomRank = nRank[i];*/ /*  no more ring system membership check is necessary because */ /*  the two neighbors are to be constitutionally equivalent atoms: */ /*   <BRKPT> */ /*  remove parity */ /* at[i].bHasStereoOrEquToStereo = 0; */ /*  remove pCS->LinearCTStereoCarb[n] */ /*   <BRKPT> */