third_party/inchi/INCHI_BASE/src/ichiqueu.c
int Check5MembTautRing( struct tagCANON_GLOBALS *pCG,
                        inp_ATOM *atom,
                        DFS_PATH *DfsPath,
                        int nLenDfsPath,
                        int nStartAtomNeighbor,
                        int nStartAtomNeighbor2,
                        int nStartAtomNeighborNeighbor,
                        T_ENDPOINT *EndPoint,
                        int nMaxNumEndPoint,
                        T_BONDPOS  *BondPos,
                        int nMaxNumBondPos,
                        int *pnNumEndPoint,
                        int *pnNumBondPos,
                        struct BalancedNetworkStructure *pBNS,
                        struct BalancedNetworkData *pBD,
                        int num_atoms )
{
#define PATH_LEN 4
    int i, j, /*m,*/ nMobile, nMobile1, nMobile2;
    int num_taut_endpoints, nNumBondPos, nNumBondPosTmp, nNumEndPoint, nNumEndPointTmp, ret;
    int endpoint;
    int n1_at = (int) DfsPath[0].at_no;
    int n2_at = (int) DfsPath[1].at_no;
    U_CHAR path_bonds[PATH_LEN + 1], bond_type;
    T_ENDPOINT EndPointTmp[2];
    T_BONDPOS  BondPosTmp[2 * PATH_LEN];
    ENDPOINT_INFO eif1, eif2;

    /*  the two root atoms (atom[n1_at] and atom[n2_at]) cannot belong */
    /*  to one and the same tautomeric group: it has been verified in MarkTautomerGroups() */

    /*  check hydrogens/endpoints */
    if (nLenDfsPath != 4)
    {
        return 0; /*  program error */
    }
    if (nStartAtomNeighbor2 >= 0 || nStartAtomNeighborNeighbor >= 0)
    {
        return 0; /*  program error: wrong call */
    }

    nNumBondPos = *pnNumBondPos;
    nNumEndPoint = *pnNumEndPoint;
    nNumEndPointTmp = 0;
    nNumBondPosTmp = 0;
    ret = 0;

    if (!nGetEndpointInfo( atom, n1_at, &eif1 ) ||
        !nGetEndpointInfo( atom, n2_at, &eif2 ))
    {
        return 0;
    }

    nMobile1 = atom[n1_at].num_H + ( atom[n1_at].charge == -1 );
    nMobile2 = atom[n2_at].num_H + ( atom[n2_at].charge == -1 );
    nMobile = nMobile1 + nMobile2;
    num_taut_endpoints = ( 0 != atom[n1_at].endpoint ) + ( 0 != atom[n2_at].endpoint ); /*  if both N atoms already are endpoints */
    /*
    if ( !(nMobile == 1 || num_taut_endpoints == 2) && !(nMobile>1 && num_taut_endpoints >= 1) ) {
        return 0;
    }
    */
    if (num_taut_endpoints == 0 && nMobile != 1)
    {
        return 0;
    }

    /* finally check whether the bonds allow moving the hydrogens */
    if (( atom[n1_at].endpoint != atom[n2_at].endpoint || !atom[n1_at].endpoint ))
    {
        int nErr;
        nErr = bExistsAnyAltPath( pCG, pBNS, pBD, atom, num_atoms, n1_at, n2_at, ALT_PATH_MODE_TAUTOM );
        if (nErr <= 0)
        {
            return nErr;
        }
    }

    /*  save endpoints */
    for (j = 0; j < 2; j++)
    {
        endpoint = j ? n1_at : n2_at;
        if (!atom[endpoint].endpoint)
        {
            /* not a known endpoint */
            /*
                        nMobile  = (atom[endpoint].charge == -1) + atom[endpoint].num_H;
                    } else {
                        nMobile  = 0;
                    }
                    if ( nMobile ) {
            */
            AddAtom2num( EndPointTmp[nNumEndPointTmp].num, atom, endpoint, 2 ); /* fill out */
            AddAtom2DA( EndPointTmp[nNumEndPointTmp].num_DA, atom, endpoint, 2 );
            /*
            EndPointTmp[nNumEndPointTmp].num[1] = (atom[endpoint].charge == -1);
            EndPointTmp[nNumEndPointTmp].num[0] = nMobile;
            for ( m = 0; m < T_NUM_ISOTOPIC; m ++ ) {
                EndPointTmp[nNumEndPointTmp].num[T_NUM_NO_ISOTOPIC+m] = atom[endpoint].num_iso_H[NUM_H_ISOTOPES-m-1];
            }
            */
        }
        else
        {
            memset( EndPointTmp + nNumEndPointTmp, 0, sizeof( EndPointTmp[0] ) );
        }
        EndPointTmp[nNumEndPointTmp].nAtomNumber = endpoint;
        EndPointTmp[nNumEndPointTmp].nGroupNumber = atom[endpoint].endpoint;
        EndPointTmp[nNumEndPointTmp].nEquNumber = 0;

        nNumEndPointTmp++;
    }

    /*  extract bonds */
    nNumBondPosTmp = 0;
    for (i = 1; i <= nLenDfsPath; i++)
    {
        bond_type = DfsPath[i].bond_type;
        path_bonds[i - 1] = bond_type;
        if (REPLACE_THE_BOND( bond_type ))
        {
            BondPosTmp[nNumBondPosTmp].nAtomNumber = DfsPath[i].at_no;
            BondPosTmp[nNumBondPosTmp].neighbor_index = DfsPath[i].bond_pos;
            nNumBondPosTmp += 2;
        }
    }
    /* path_bonds is from at_n2 to at_n1 */
    if (!( i = are_alt_bonds( path_bonds, nLenDfsPath ) ))
    {
        return 0;
    }
    /* i is a bond type of the last bond to at_n1, the first bond from at_n2 is 2-i if i=1 or 2 */

    /* single bond at n1_at: it should have a mobile atom, n2_at should not */
    if (i == BOND_SINGLE && ( !atom[n1_at].endpoint && !eif1.cDonor || !atom[n2_at].endpoint && !eif2.cAcceptor ) ||
        /* double bond at n1_at: it should not have a mobile atom, n2_at should */
        i == BOND_DOUBLE && ( !atom[n1_at].endpoint && !eif1.cAcceptor || !atom[n2_at].endpoint && !eif2.cDonor ))
    {
        return 0; /* bond pattern does not fit */
    }

    nNumBondPos = AddBondsPos( atom, BondPosTmp, nNumBondPosTmp, BondPos, nMaxNumBondPos, nNumBondPos );
    nNumEndPoint = AddEndPoints( EndPointTmp, nNumEndPointTmp, EndPoint, nMaxNumEndPoint, nNumEndPoint );

    if (nNumBondPos >= 0 && nNumEndPoint >= 0)
    {
        if (ret = ( nNumBondPos > *pnNumBondPos ) || ( nNumEndPoint > *pnNumEndPoint ))
        {
            *pnNumBondPos = nNumBondPos;
            *pnNumEndPoint = nNumEndPoint;
        }
    }
    return ret;

#undef PATH_LEN
}
/****************************************************************************
  check if a tautomeric 5-member ring (pyrazole derivatives) has been found
****************************************************************************/
check if a tautomeric 5-member ring (pyrazole derivatives) has been found
check if a tautomeric 5 - member ring ( pyrazole derivatives ) has been found
int Check5MembTautRing( struct tagCANON_GLOBALS *pCG,
                        inp_ATOM *atom,
                        DFS_PATH *DfsPath,
                        int nLenDfsPath,
                        int nStartAtomNeighbor,
                        int nStartAtomNeighbor2,
                        int nStartAtomNeighborNeighbor,
                        T_ENDPOINT *EndPoint,
                        int nMaxNumEndPoint,
                        T_BONDPOS  *BondPos,
                        int nMaxNumBondPos,
                        int *pnNumEndPoint,
                        int *pnNumBondPos,
                        struct BalancedNetworkStructure *pBNS,
                        struct BalancedNetworkData *pBD,
                        int num_atoms )
{
#define PATH_LEN 4
    int i, j,  nMobile, nMobile1, nMobile2;
    int num_taut_endpoints, nNumBondPos, nNumBondPosTmp, nNumEndPoint, nNumEndPointTmp, ret;
    int endpoint;
    int n1_at = (int) DfsPath[0].at_no;
    int n2_at = (int) DfsPath[1].at_no;
    U_CHAR path_bonds[PATH_LEN + 1], bond_type;
    T_ENDPOINT EndPointTmp[2];
    T_BONDPOS  BondPosTmp[2 * PATH_LEN];
    ENDPOINT_INFO eif1, eif2;
    if (nLenDfsPath != 4)
    {
        return 0; 
    }
    if (nStartAtomNeighbor2 >= 0 || nStartAtomNeighborNeighbor >= 0)
    {
        return 0; 
    }
    nNumBondPos = *pnNumBondPos;
    nNumEndPoint = *pnNumEndPoint;
    nNumEndPointTmp = 0;
    nNumBondPosTmp = 0;
    ret = 0;
    if (!nGetEndpointInfo( atom, n1_at, &eif1 ) ||
        !nGetEndpointInfo( atom, n2_at, &eif2 ))
    {
        return 0;
    }
    nMobile1 = atom[n1_at].num_H + ( atom[n1_at].charge == -1 );
    nMobile2 = atom[n2_at].num_H + ( atom[n2_at].charge == -1 );
    nMobile = nMobile1 + nMobile2;
    num_taut_endpoints = ( 0 != atom[n1_at].endpoint ) + ( 0 != atom[n2_at].endpoint ); 
    if (num_taut_endpoints == 0 && nMobile != 1)
    {
        return 0;
    }
    if (( atom[n1_at].endpoint != atom[n2_at].endpoint || !atom[n1_at].endpoint ))
    {
        int nErr;
        nErr = bExistsAnyAltPath( pCG, pBNS, pBD, atom, num_atoms, n1_at, n2_at, ALT_PATH_MODE_TAUTOM );
        if (nErr <= 0)
        {
            return nErr;
        }
    }
    for (j = 0; j < 2; j++)
    {
        endpoint = j ? n1_at : n2_at;
        if (!atom[endpoint].endpoint)
        {
            AddAtom2num( EndPointTmp[nNumEndPointTmp].num, atom, endpoint, 2 ); 
            AddAtom2DA( EndPointTmp[nNumEndPointTmp].num_DA, atom, endpoint, 2 );
        }
        else
        {
            memset( EndPointTmp + nNumEndPointTmp, 0, sizeof( EndPointTmp[0] ) );
        }
        EndPointTmp[nNumEndPointTmp].nAtomNumber = endpoint;
        EndPointTmp[nNumEndPointTmp].nGroupNumber = atom[endpoint].endpoint;
        EndPointTmp[nNumEndPointTmp].nEquNumber = 0;
        nNumEndPointTmp++;
    }
    nNumBondPosTmp = 0;
    for (i = 1; i <= nLenDfsPath; i++)
    {
        bond_type = DfsPath[i].bond_type;
        path_bonds[i - 1] = bond_type;
        if (REPLACE_THE_BOND( bond_type ))
        {
            BondPosTmp[nNumBondPosTmp].nAtomNumber = DfsPath[i].at_no;
            BondPosTmp[nNumBondPosTmp].neighbor_index = DfsPath[i].bond_pos;
            nNumBondPosTmp += 2;
        }
    }
    if (!( i = are_alt_bonds( path_bonds, nLenDfsPath ) ))
    {
        return 0;
    }
    if (i == BOND_SINGLE && ( !atom[n1_at].endpoint && !eif1.cDonor || !atom[n2_at].endpoint && !eif2.cAcceptor ) ||
        i == BOND_DOUBLE && ( !atom[n1_at].endpoint && !eif1.cAcceptor || !atom[n2_at].endpoint && !eif2.cDonor ))
    {
        return 0; 
    }
    nNumBondPos = AddBondsPos( atom, BondPosTmp, nNumBondPosTmp, BondPos, nMaxNumBondPos, nNumBondPos );
    nNumEndPoint = AddEndPoints( EndPointTmp, nNumEndPointTmp, EndPoint, nMaxNumEndPoint, nNumEndPoint );
    if (nNumBondPos >= 0 && nNumEndPoint >= 0)
    {
        if (ret = ( nNumBondPos > *pnNumBondPos ) || ( nNumEndPoint > *pnNumEndPoint ))
        {
            *pnNumBondPos = nNumBondPos;
            *pnNumEndPoint = nNumEndPoint;
        }
    }
    return ret;
#undef PATH_LEN
}
int Check5MembTautRing ( struct tagCANON_GLOBALS * pCG , inp_ATOM * atom , DFS_PATH * DfsPath , int nLenDfsPath , int nStartAtomNeighbor , int nStartAtomNeighbor2 , int nStartAtomNeighborNeighbor , T_ENDPOINT * EndPoint , int nMaxNumEndPoint , T_BONDPOS * BondPos , int nMaxNumBondPos , int * pnNumEndPoint , int * pnNumBondPos , struct BalancedNetworkStructure * pBNS , struct BalancedNetworkData * pBD , int num_atoms ) { #define PATH_LEN  4 int i , j , nMobile , nMobile1 , nMobile2 ; int num_taut_endpoints , nNumBondPos , nNumBondPosTmp , nNumEndPoint , nNumEndPointTmp , ret ; int endpoint ; int n1_at = ( int ) DfsPath [ 0 ] . at_no ; int n2_at = ( int ) DfsPath [ 1 ] . at_no ; U_CHAR path_bonds [ PATH_LEN + 1 ] , bond_type ; T_ENDPOINT EndPointTmp [ 2 ] ; T_BONDPOS BondPosTmp [ 2 * PATH_LEN ] ; ENDPOINT_INFO eif1 , eif2 ; if ( nLenDfsPath != 4 ) { return 0 ; } if ( nStartAtomNeighbor2 >= 0 || nStartAtomNeighborNeighbor >= 0 ) { return 0 ; } nNumBondPos = * pnNumBondPos ; nNumEndPoint = * pnNumEndPoint ; nNumEndPointTmp = 0 ; nNumBondPosTmp = 0 ; ret = 0 ; if ( ! nGetEndpointInfo ( atom , n1_at , & eif1 ) || ! nGetEndpointInfo ( atom , n2_at , & eif2 ) ) { return 0 ; } nMobile1 = atom [ n1_at ] . num_H + ( atom [ n1_at ] . charge == -1 ) ; nMobile2 = atom [ n2_at ] . num_H + ( atom [ n2_at ] . charge == -1 ) ; nMobile = nMobile1 + nMobile2 ; num_taut_endpoints = ( 0 != atom [ n1_at ] . endpoint ) + ( 0 != atom [ n2_at ] . endpoint ) ; if ( num_taut_endpoints == 0 && nMobile != 1 ) { return 0 ; } if ( ( atom [ n1_at ] . endpoint != atom [ n2_at ] . endpoint || ! atom [ n1_at ] . endpoint ) ) { int nErr ; nErr = bExistsAnyAltPath ( pCG , pBNS , pBD , atom , num_atoms , n1_at , n2_at , ALT_PATH_MODE_TAUTOM ) ; if ( nErr <= 0 ) { return nErr ; } } for ( j = 0 ; j < 2 ; j ++ ) { endpoint = j ? n1_at : n2_at ; if ( ! atom [ endpoint ] . endpoint ) { AddAtom2num ( EndPointTmp [ nNumEndPointTmp ] . num , atom , endpoint , 2 ) ; AddAtom2DA ( EndPointTmp [ nNumEndPointTmp ] . num_DA , atom , endpoint , 2 ) ; } else { memset ( EndPointTmp + nNumEndPointTmp , 0 , sizeof ( EndPointTmp [ 0 ] ) ) ; } EndPointTmp [ nNumEndPointTmp ] . nAtomNumber = endpoint ; EndPointTmp [ nNumEndPointTmp ] . nGroupNumber = atom [ endpoint ] . endpoint ; EndPointTmp [ nNumEndPointTmp ] . nEquNumber = 0 ; nNumEndPointTmp ++ ; } nNumBondPosTmp = 0 ; for ( i = 1 ; i <= nLenDfsPath ; i ++ ) { bond_type = DfsPath [ i ] . bond_type ; path_bonds [ i - 1 ] = bond_type ; if ( REPLACE_THE_BOND ( bond_type ) ) { BondPosTmp [ nNumBondPosTmp ] . nAtomNumber = DfsPath [ i ] . at_no ; BondPosTmp [ nNumBondPosTmp ] . neighbor_index = DfsPath [ i ] . bond_pos ; nNumBondPosTmp += 2 ; } } if ( ! ( i = are_alt_bonds ( path_bonds , nLenDfsPath ) ) ) { return 0 ; } if ( i == BOND_SINGLE && ( ! atom [ n1_at ] . endpoint && ! eif1 . cDonor || ! atom [ n2_at ] . endpoint && ! eif2 . cAcceptor ) || i == BOND_DOUBLE && ( ! atom [ n1_at ] . endpoint && ! eif1 . cAcceptor || ! atom [ n2_at ] . endpoint && ! eif2 . cDonor ) ) { return 0 ; } nNumBondPos = AddBondsPos ( atom , BondPosTmp , nNumBondPosTmp , BondPos , nMaxNumBondPos , nNumBondPos ) ; nNumEndPoint = AddEndPoints ( EndPointTmp , nNumEndPointTmp , EndPoint , nMaxNumEndPoint , nNumEndPoint ) ; if ( nNumBondPos >= 0 && nNumEndPoint >= 0 ) { if ( ret = ( nNumBondPos > * pnNumBondPos ) || ( nNumEndPoint > * pnNumEndPoint ) ) { * pnNumBondPos = nNumBondPos ; * pnNumEndPoint = nNumEndPoint ; } } return ret ; #undef  PATH_LEN }
check if a tautomeric 5-member ring (pyrazole derivatives) has been found
check if a tautomeric 5 - member ring ( pyrazole derivatives ) has been found
/*m,*/ /*  the two root atoms (atom[n1_at] and atom[n2_at]) cannot belong */ /*  to one and the same tautomeric group: it has been verified in MarkTautomerGroups() */ /*  check hydrogens/endpoints */ /*  program error */ /*  program error: wrong call */ /*  if both N atoms already are endpoints */ /*
    if ( !(nMobile == 1 || num_taut_endpoints == 2) && !(nMobile>1 && num_taut_endpoints >= 1) ) {
        return 0;
    }
    */ /* finally check whether the bonds allow moving the hydrogens */ /*  save endpoints */ /* not a known endpoint */ /*
                        nMobile  = (atom[endpoint].charge == -1) + atom[endpoint].num_H;
                    } else {
                        nMobile  = 0;
                    }
                    if ( nMobile ) {
            */ /* fill out */ /*
            EndPointTmp[nNumEndPointTmp].num[1] = (atom[endpoint].charge == -1);
            EndPointTmp[nNumEndPointTmp].num[0] = nMobile;
            for ( m = 0; m < T_NUM_ISOTOPIC; m ++ ) {
                EndPointTmp[nNumEndPointTmp].num[T_NUM_NO_ISOTOPIC+m] = atom[endpoint].num_iso_H[NUM_H_ISOTOPES-m-1];
            }
            */ /*  extract bonds */ /* path_bonds is from at_n2 to at_n1 */ /* i is a bond type of the last bond to at_n1, the first bond from at_n2 is 2-i if i=1 or 2 */ /* single bond at n1_at: it should have a mobile atom, n2_at should not */ /* double bond at n1_at: it should not have a mobile atom, n2_at should */ /* bond pattern does not fit */