third_party/inchi/INCHI_BASE/src/ichicans.c
int RemoveKnownNonStereoBondParities( sp_ATOM       *at,
                                      int           num_atoms,
                                      const AT_RANK *nCanonRank,
                                      const AT_RANK *nRank,
                                      CANON_STAT    *pCS )
{
    int j, n, m, ret;

    int i1, n1, s2;
    AT_RANK nAtomRank1, nAtomRank2, neigh[3], opposite_atom, *nVisited = NULL;
    ret = 0;
    for (i1 = 0; i1 < num_atoms; i1++)
    {
        if (at[i1].valence != 3 || !at[i1].stereo_bond_neighbor[0])
        {
            continue;
        }
        for (n1 = 0; n1 < MAX_NUM_STEREO_BONDS && ( s2 = at[i1].stereo_bond_neighbor[n1] ); n1++)
        {
            if (!PARITY_CALCULATE( at[i1].stereo_bond_parity[n1] ) && PARITY_WELL_DEF( at[i1].stereo_bond_parity[n1] ))
            {
                continue;
            }
            opposite_atom = (AT_RANK) ( s2 - 1 );
            /* s2 = at[i1].neighbor[m=(int)at[i1].stereo_bond_ord[n1]]; */
            m = (int) at[i1].stereo_bond_ord[n1];
            for (j = 0, n = 0; j < at[i1].valence; j++)
            {
                /* if ( at[i1].neighbor[j] != s2 ) */
                if (j != m)
                {
                    neigh[n++] = at[i1].neighbor[j];
                }
            }
            if (n > 2)
            {
                ret = CT_STEREOBOND_ERROR;  /*   <BRKPT> */
                goto exit_function;
            }
            if (n != 2 || nRank[(int) neigh[0]] != nRank[(int) neigh[1]])
            {
                continue; /*  may happen if another half-bond has not a defined parity */
            }
            if (at[i1].nRingSystem == at[(int) neigh[0]].nRingSystem)
            {
                continue;  /*  no more ring system membership check is necessary because     */
            }              /*  the two neighbors are to be constitutionally equivalent atoms */
            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[i1] = 1;
            if (PathsHaveIdenticalKnownParities( at, (AT_RANK) i1, neigh[0], (AT_RANK) i1, neigh[1], nVisited, nVisited, nRank, nCanonRank, 1 ))
            {
                if (!RemoveOneStereoBond( at, i1, /* atom number*/ n1 /* stereo bond number*/ ))
                {
                    ret = CT_STEREOBOND_ERROR;  /*   <BRKPT> */
                    goto exit_function;
                }
                n1--; /*  cycle counter may temporarily become negative */
                /*  Remove from pCS */
                nAtomRank1 = inchi_max( nCanonRank[i1], nCanonRank[opposite_atom] );
                nAtomRank2 = inchi_min( nCanonRank[i1], nCanonRank[opposite_atom] );
                for (n = 0, m = pCS->nLenLinearCTStereoDble - 1; n <= m; n++)
                {
                    if (pCS->LinearCTStereoDble[n].at_num1 == nAtomRank1 &&
                         pCS->LinearCTStereoDble[n].at_num2 == nAtomRank2)
                    {
                        if (n < m)
                        { /*  remove pCS->LinearCTStereoDble[n] */
                            memmove( pCS->LinearCTStereoDble + n,
                                     pCS->LinearCTStereoDble + n + 1,
                                     ( m - n ) * sizeof( pCS->LinearCTStereoDble[0] ) );
                        }
                        pCS->nLenLinearCTStereoDble--;
#if ( bRELEASE_VERSION == 0 )
                        pCS->bExtract |= EXTR_KNOWN_USED_TO_REMOVE_PARITY;
#endif
                        m = -1;   /*  set flag "found" */
                        break;
                    }
                }
                if (m >= 0)
                {
                    ret = CT_STEREOCOUNT_ERR;  /*  bond not found  <BRKPT> */
                    goto exit_function;
                }
                ret++;  /*  number of removed known in advance non-stereo bonds */
            }
        }
    }

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

    return ret;
}
/****************************************************************************/
/*  Remove stereo marks from the bonds that are known to be non-stereo      */
/*  (compare neighbors if they are attached by cut-edges)                   */
/****************************************************************************/
Remove stereo marks from the bonds that are known to be non-stereo
(compare neighbors if they are attached by cut-edges)
Remove stereo marks from the bonds that are known to be non - stereo ( compare neighbors if they are attached by cut - edges )
int RemoveKnownNonStereoBondParities( sp_ATOM       *at,
                                      int           num_atoms,
                                      const AT_RANK *nCanonRank,
                                      const AT_RANK *nRank,
                                      CANON_STAT    *pCS )
{
    int j, n, m, ret;
    int i1, n1, s2;
    AT_RANK nAtomRank1, nAtomRank2, neigh[3], opposite_atom, *nVisited = NULL;
    ret = 0;
    for (i1 = 0; i1 < num_atoms; i1++)
    {
        if (at[i1].valence != 3 || !at[i1].stereo_bond_neighbor[0])
        {
            continue;
        }
        for (n1 = 0; n1 < MAX_NUM_STEREO_BONDS && ( s2 = at[i1].stereo_bond_neighbor[n1] ); n1++)
        {
            if (!PARITY_CALCULATE( at[i1].stereo_bond_parity[n1] ) && PARITY_WELL_DEF( at[i1].stereo_bond_parity[n1] ))
            {
                continue;
            }
            opposite_atom = (AT_RANK) ( s2 - 1 );
            m = (int) at[i1].stereo_bond_ord[n1];
            for (j = 0, n = 0; j < at[i1].valence; j++)
            {
                if (j != m)
                {
                    neigh[n++] = at[i1].neighbor[j];
                }
            }
            if (n > 2)
            {
                ret = CT_STEREOBOND_ERROR;  
                goto exit_function;
            }
            if (n != 2 || nRank[(int) neigh[0]] != nRank[(int) neigh[1]])
            {
                continue; 
            }
            if (at[i1].nRingSystem == at[(int) neigh[0]].nRingSystem)
            {
                continue;  
            }              
            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[i1] = 1;
            if (PathsHaveIdenticalKnownParities( at, (AT_RANK) i1, neigh[0], (AT_RANK) i1, neigh[1], nVisited, nVisited, nRank, nCanonRank, 1 ))
            {
                if (!RemoveOneStereoBond( at, i1,  n1  ))
                {
                    ret = CT_STEREOBOND_ERROR;  
                    goto exit_function;
                }
                n1--; 
                nAtomRank1 = inchi_max( nCanonRank[i1], nCanonRank[opposite_atom] );
                nAtomRank2 = inchi_min( nCanonRank[i1], nCanonRank[opposite_atom] );
                for (n = 0, m = pCS->nLenLinearCTStereoDble - 1; n <= m; n++)
                {
                    if (pCS->LinearCTStereoDble[n].at_num1 == nAtomRank1 &&
                         pCS->LinearCTStereoDble[n].at_num2 == nAtomRank2)
                    {
                        if (n < m)
                        { 
                            memmove( pCS->LinearCTStereoDble + n,
                                     pCS->LinearCTStereoDble + n + 1,
                                     ( m - n ) * sizeof( pCS->LinearCTStereoDble[0] ) );
                        }
                        pCS->nLenLinearCTStereoDble--;
#if ( bRELEASE_VERSION == 0 )
                        pCS->bExtract |= EXTR_KNOWN_USED_TO_REMOVE_PARITY;
#endif
                        m = -1;   
                        break;
                    }
                }
                if (m >= 0)
                {
                    ret = CT_STEREOCOUNT_ERR;  
                    goto exit_function;
                }
                ret++;  
            }
        }
    }
exit_function:
    if (nVisited)
    {
        inchi_free( nVisited );
    }
    return ret;
}
int RemoveKnownNonStereoBondParities ( sp_ATOM * at , int num_atoms , const AT_RANK * nCanonRank , const AT_RANK * nRank , CANON_STAT * pCS ) { int j , n , m , ret ; int i1 , n1 , s2 ; AT_RANK nAtomRank1 , nAtomRank2 , neigh [ 3 ] , opposite_atom , * nVisited = NULL ; ret = 0 ; for ( i1 = 0 ; i1 < num_atoms ; i1 ++ ) { if ( at [ i1 ] . valence != 3 || ! at [ i1 ] . stereo_bond_neighbor [ 0 ] ) { continue ; } for ( n1 = 0 ; n1 < MAX_NUM_STEREO_BONDS && ( s2 = at [ i1 ] . stereo_bond_neighbor [ n1 ] ) ; n1 ++ ) { if ( ! PARITY_CALCULATE ( at [ i1 ] . stereo_bond_parity [ n1 ] ) && PARITY_WELL_DEF ( at [ i1 ] . stereo_bond_parity [ n1 ] ) ) { continue ; } opposite_atom = ( AT_RANK ) ( s2 - 1 ) ; m = ( int ) at [ i1 ] . stereo_bond_ord [ n1 ] ; for ( j = 0 , n = 0 ; j < at [ i1 ] . valence ; j ++ ) { if ( j != m ) { neigh [ n ++ ] = at [ i1 ] . neighbor [ j ] ; } } if ( n > 2 ) { ret = CT_STEREOBOND_ERROR ; goto exit_function ; } if ( n != 2 || nRank [ ( int ) neigh [ 0 ] ] != nRank [ ( int ) neigh [ 1 ] ] ) { continue ; } if ( at [ i1 ] . nRingSystem == at [ ( int ) neigh [ 0 ] ] . nRingSystem ) { continue ; } 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 [ i1 ] = 1 ; if ( PathsHaveIdenticalKnownParities ( at , ( AT_RANK ) i1 , neigh [ 0 ] , ( AT_RANK ) i1 , neigh [ 1 ] , nVisited , nVisited , nRank , nCanonRank , 1 ) ) { if ( ! RemoveOneStereoBond ( at , i1 , n1 ) ) { ret = CT_STEREOBOND_ERROR ; goto exit_function ; } n1 -- ; nAtomRank1 = inchi_max ( nCanonRank [ i1 ] , nCanonRank [ opposite_atom ] ) ; nAtomRank2 = inchi_min ( nCanonRank [ i1 ] , nCanonRank [ opposite_atom ] ) ; for ( n = 0 , m = pCS -> nLenLinearCTStereoDble - 1 ; n <= m ; n ++ ) { if ( pCS -> LinearCTStereoDble [ n ] . at_num1 == nAtomRank1 && pCS -> LinearCTStereoDble [ n ] . at_num2 == nAtomRank2 ) { if ( n < m ) { memmove ( pCS -> LinearCTStereoDble + n , pCS -> LinearCTStereoDble + n + 1 , ( m - n ) * sizeof ( pCS -> LinearCTStereoDble [ 0 ] ) ) ; } pCS -> nLenLinearCTStereoDble -- ; #if ( bRELEASE_VERSION == 0 ) pCS -> bExtract |= EXTR_KNOWN_USED_TO_REMOVE_PARITY ; #endif m = -1 ; break ; } } if ( m >= 0 ) { ret = CT_STEREOCOUNT_ERR ; goto exit_function ; } ret ++ ; } } } exit_function : if ( nVisited ) { inchi_free ( nVisited ) ; } return ret ; }
Remove stereo marks from the bonds that are known to be non-stereo
(compare neighbors if they are attached by cut-edges)
Remove stereo marks from the bonds that are known to be non - stereo ( compare neighbors if they are attached by cut - edges )
/* s2 = at[i1].neighbor[m=(int)at[i1].stereo_bond_ord[n1]]; */ /* if ( at[i1].neighbor[j] != s2 ) */ /*   <BRKPT> */ /*  may happen if another half-bond has not a defined parity */ /*  no more ring system membership check is necessary because     */ /*  the two neighbors are to be constitutionally equivalent atoms */ /*   <BRKPT> */ /* atom number*/ /* stereo bond number*/ /*   <BRKPT> */ /*  cycle counter may temporarily become negative */ /*  Remove from pCS */ /*  remove pCS->LinearCTStereoDble[n] */ /*  set flag "found" */ /*  bond not found  <BRKPT> */ /*  number of removed known in advance non-stereo bonds */