LCOV - code coverage report
Current view: top level - src - aromaticity.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 0.0 % 82 0
Test Date: 2026-10-14 12:14:55 Functions: 0.0 % 6 0
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0.0 % 106 0

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * SPDX-License-Identifier: MIT
       3                 :             :  * Copyright (c) 2024 IUPAC and InChI Trust
       4                 :             :  */
       5                 :             : 
       6                 :             : #include <stdlib.h>
       7                 :             : #include <string.h>
       8                 :             : 
       9                 :             : #include "mode.h"
      10                 :             : #include "aromaticity.h"
      11                 :             : #include "ichinorm.h"  /* declares mark_alt_bonds_and_taut_groups + engine types */
      12                 :             : #include "util.h"      /* is_in_the_list */
      13                 :             : #include "ichierr.h"
      14                 :             : 
      15                 :             : #include "bcf_s.h"
      16                 :             : 
      17                 :             : 
      18                 :             : /****************************************************************************/
      19                 :           0 : int fix_aromatic_oxygen_and_sulfur( inp_ATOM *atom )
      20                 :             : {
      21         [ #  # ]:           0 :     if (!atom->elname[1] &&
      22   [ #  #  #  # ]:           0 :          (atom->elname[0] == 'O' || atom->elname[0] == 'S') &&
      23   [ #  #  #  #  :           0 :          atom->valence == 2 && !atom->charge && !atom->radical &&
                   #  # ]
      24         [ #  # ]:           0 :          atom->bond_type[0] + atom->bond_type[1] == 3)
      25                 :             :     {
      26                 :           0 :         atom->charge = 1;
      27                 :           0 :         return 1; /* fixed */
      28                 :             :     }
      29                 :             : 
      30                 :           0 :     return 0;
      31                 :             : }
      32                 :             : 
      33                 :             : 
      34                 :             : /****************************************************************************/
      35                 :           0 : int check_arom_chain( inp_ATOM *at,
      36                 :             :                       int cur /* first*/,
      37                 :             :                       int from,
      38                 :             :                       int last,
      39                 :             :                       int len )
      40                 :             : {
      41                 :             :     int i, num;
      42                 :           0 :     num = 0;
      43                 :             :     do
      44                 :             :     {
      45                 :             :         /* check this on all except at[last], which is typically different */
      46         [ #  # ]:           0 :         if (at[cur].el_number != EL_NUMBER_C ||
      47         [ #  # ]:           0 :              at[cur].valence != 2 ||
      48         [ #  # ]:           0 :              at[cur].chem_bonds_valence != 3 ||
      49         [ #  # ]:           0 :              at[cur].num_H != 1)
      50                 :             :         {
      51                 :           0 :             goto check_next_derivative;
      52                 :             :         }
      53                 :             :         /* bond to the next atom - check on all, cur..last, atoms */
      54                 :           0 :         i = ( at[cur].neighbor[0] == from ); /* index of a bond to the next atom */
      55         [ #  # ]:           0 :         if (at[cur].bond_type[i] != BOND_ALTERN)
      56                 :             :         {
      57                 :           0 :             goto check_next_derivative;
      58                 :             :         }
      59                 :           0 :         num++; /* checks are complete */
      60                 :             :                /* prepare for the next atom */
      61                 :           0 :         from = cur;
      62                 :           0 :         cur = at[cur].neighbor[i];
      63   [ #  #  #  # ]:           0 :     } while (cur != last && num < len);
      64                 :             : 
      65   [ #  #  #  # ]:           0 :     return ( cur == last && ++num == len );
      66                 :             : 
      67                 :           0 : check_next_derivative:
      68                 :             : 
      69                 :           0 :     return 0;
      70                 :             : }
      71                 :             : 
      72                 :             : 
      73                 :             : #if ( RING2CHAIN == 1 || UNDERIVATIZE == 1 )
      74                 :             : /****************************************************************************/
      75                 :           0 : int mark_arom_bonds( struct tagINCHI_CLOCK *ic, struct tagCANON_GLOBALS *pCG, inp_ATOM *at, int num_atoms )
      76                 :             : {
      77                 :           0 :     INCHI_MODE bTautFlags = 0, bTautFlagsDone = 0;
      78                 :           0 :     inp_ATOM *at_fixed_bonds_out = NULL;
      79                 :           0 :     T_GROUP_INFO *t_group_info = NULL;
      80                 :             :     int ret;
      81                 :             : 
      82                 :           0 :     ret = mark_alt_bonds_and_taut_groups( ic, pCG, at, at_fixed_bonds_out, num_atoms,
      83                 :             :                                           NULL,
      84                 :             :                                           t_group_info, &bTautFlags, &bTautFlagsDone, 0, NULL );
      85                 :             : 
      86                 :           0 :     return ret;
      87                 :             : }
      88                 :             : 
      89                 :             : 
      90                 :             : /****************************************************************************/
      91                 :           0 : int is_C_unsat_not_arom( inp_ATOM *at, int i )
      92                 :             : {
      93                 :             :     int j, neigh, num_arom, num_DB;
      94         [ #  # ]:           0 :     if (at[i].el_number != EL_NUMBER_C ||
      95         [ #  # ]:           0 :          at[i].valence == at[i].chem_bonds_valence || /* no double/triple bonds */
      96         [ #  # ]:           0 :          at[i].valence + 1 < at[i].chem_bonds_valence || /* >1 double bond or >=1 triple bond */
      97         [ #  # ]:           0 :          at[i].chem_bonds_valence + at[i].num_H != 4 || /* C has wrong valence */
      98   [ #  #  #  # ]:           0 :          at[i].charge || at[i].radical)
      99                 :           0 :         return 0;
     100                 :           0 :     num_arom = num_DB = 0;
     101         [ #  # ]:           0 :     for (j = 0; j < at[i].valence; j++)
     102                 :             :     {
     103                 :           0 :         neigh = at[i].neighbor[j];
     104                 :           0 :         num_arom += at[i].bond_type[j] == BOND_TYPE_ALTERN;
     105         [ #  # ]:           0 :         if (( at[neigh].el_number == EL_NUMBER_O ||
     106         [ #  # ]:           0 :               at[neigh].el_number == EL_NUMBER_S ) &&
     107   [ #  #  #  # ]:           0 :              !at[neigh].num_H && 1 == at[neigh].valence &&
     108         [ #  # ]:           0 :              2 == at[neigh].chem_bonds_valence)
     109                 :             :         {
     110                 :           0 :             continue; /* do not count double bonds to terminal =O or =S */
     111                 :             :         }
     112                 :           0 :         num_DB += at[i].bond_type[j] == BOND_TYPE_DOUBLE;
     113                 :             :     }
     114                 :             : 
     115   [ #  #  #  # ]:           0 :     return num_DB && !num_arom;
     116                 :             : }
     117                 :             : 
     118                 :             : 
     119                 :             : /****************************************************************************/
     120                 :           0 : int is_Aryl( inp_ATOM *at, int outside_point, int attachment_pont )
     121                 :             : {
     122                 :             :     int i, num_arom_bonds, neigh;
     123         [ #  # ]:           0 :     if (at[attachment_pont].el_number == EL_NUMBER_C &&
     124   [ #  #  #  # ]:           0 :          at[attachment_pont].valence == 3 && at[attachment_pont].chem_bonds_valence == 4 &&
     125   [ #  #  #  #  :           0 :          !at[attachment_pont].num_H && !at[attachment_pont].charge && !at[attachment_pont].radical)
                   #  # ]
     126                 :             :     {
     127         [ #  # ]:           0 :         for (i = 0, num_arom_bonds = 0; i < at[attachment_pont].valence; i++)
     128                 :             :         {
     129                 :           0 :             neigh = at[attachment_pont].neighbor[i];
     130         [ #  # ]:           0 :             if (neigh != outside_point)
     131                 :             :             {
     132         [ #  # ]:           0 :                 num_arom_bonds += ( at[attachment_pont].bond_type[i] == BOND_ALTERN &&
     133   [ #  #  #  # ]:           0 :                     ( at[neigh].el_number == EL_NUMBER_C || at[neigh].el_number == EL_NUMBER_N ) );
     134                 :             :             }
     135                 :             :         }
     136                 :           0 :         return ( num_arom_bonds == 2 );
     137                 :             :     }
     138                 :             : 
     139                 :           0 :     return 0;
     140                 :             : }
     141                 :             : #endif /* ( RING2CHAIN == 1 || UNDERIVATIZE == 1 ) */
     142                 :             : 
     143                 :             : 
     144                 :             : #ifdef FIX_UNDERIV_TO_SDF
     145                 :             : /****************************************************************************/
     146                 :           0 : int replace_arom_bonds( inp_ATOM *at,
     147                 :             :                         int num_atoms,
     148                 :             :                         inp_ATOM *at2,
     149                 :             :                         int num_atoms2 )
     150                 :             : {
     151                 :           0 :     int i, j, num_err = 0;
     152                 :             : 
     153         [ #  # ]:           0 :     for (i = 0; i < num_atoms; i++)
     154                 :             :     {
     155         [ #  # ]:           0 :         for (j = 0; j < at[i].valence; j++)
     156                 :             :         {
     157         [ #  # ]:           0 :             if (at[i].bond_type[j] > BOND_TRIPLE)
     158                 :             :             {
     159                 :             :                 /* find pairs of atoms using orig. atom numbers */
     160                 :             :                 int i1, i2;
     161                 :           0 :                 char bSuccess = 0;
     162                 :           0 :                 int neigh = at[i].neighbor[j];
     163                 :           0 :                 AT_NUMB orig_no1 = at[i].orig_at_number;
     164                 :           0 :                 AT_NUMB orig_no2 = at[neigh].orig_at_number;
     165   [ #  #  #  # ]:           0 :                 for (i1 = 0; i1 < num_atoms2 && at2[i1].orig_at_number != orig_no1; i1++)
     166                 :             :                 {
     167                 :             :                     ;
     168                 :             :                 }
     169   [ #  #  #  # ]:           0 :                 for (i2 = 0; i2 < num_atoms2 && at2[i2].orig_at_number != orig_no2; i2++)
     170                 :             :                 {
     171                 :             :                     ;
     172                 :             :                 }
     173   [ #  #  #  # ]:           0 :                 if (i1 < num_atoms2 && i2 < num_atoms2)
     174                 :             :                 {
     175                 :           0 :                     AT_NUMB *p1 = is_in_the_list( at2[i1].neighbor, (AT_NUMB) i2, at2[i1].valence );
     176                 :           0 :                     AT_NUMB *pneigh = is_in_the_list( at[neigh].neighbor, (AT_NUMB) i, at[neigh].valence );
     177   [ #  #  #  # ]:           0 :                     if (p1 && pneigh)
     178                 :             :                     {
     179                 :           0 :                         int n1 = p1 - at2[i1].neighbor;
     180                 :           0 :                         int nneigh = pneigh - at[neigh].neighbor;
     181                 :           0 :                         at[i].bond_type[j] = at[neigh].bond_type[nneigh] = at2[i1].bond_type[n1];
     182                 :           0 :                         bSuccess = 1;
     183                 :             :                     }
     184                 :             :                 }
     185         [ #  # ]:           0 :                 if (!bSuccess)
     186                 :             :                 {
     187                 :             : #ifdef _DEBUG
     188                 :             :                     int stop_here = 1;
     189                 :             : #endif
     190                 :           0 :                     num_err++;
     191                 :             :                 }
     192                 :             :             }
     193                 :             :         }
     194                 :             :     }
     195                 :             : 
     196                 :           0 :     return num_err;
     197                 :             : }
     198                 :             : #endif /* FIX_UNDERIV_TO_SDF */
        

Generated by: LCOV version 2.0-1