LCOV - code coverage report
Current view: top level - src - ichicans.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 36.0 % 870 313
Test Date: 2026-10-14 12:14:55 Functions: 55.6 % 27 15
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 28.6 % 864 247

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * SPDX-License-Identifier: MIT
       3                 :             :  * Copyright (c) 2024 IUPAC and InChI Trust
       4                 :             :  */
       5                 :             : 
       6                 :             : 
       7                 :             : #include <stdlib.h>
       8                 :             : #include <string.h>
       9                 :             : 
      10                 :             : #include "mode.h"
      11                 :             : #include "ichicant.h"
      12                 :             : #include "ichicomn.h"
      13                 :             : #include "ichister.h"
      14                 :             : 
      15                 :             : #include "bcf_s.h"
      16                 :             : 
      17                 :             : typedef struct tagStereoBondNeighbor
      18                 :             : {
      19                 :             :     /*  *n = sort key */
      20                 :             :     AT_RANK       nRank;            /* 1 opposite atom rank; equal ranks mean constit. equivalence  */
      21                 :             :     AT_RANK       nNeighRank1;      /* rank of the neighbor in the direction to the opposite atom   */
      22                 :             :     AT_RANK       nNeighRank2;      /* rank of the opposite atom neighbor in the direction          */
      23                 :             :                                     /* to the current atom                                          */
      24                 :             :     AT_RANK       num;              /* number of same type bonds to constitutionally                */
      25                 :             :                                     /* equivalent neighbors                                         */
      26                 :             :     AT_RANK       num_any_parity;   /*  at least one atom has parity in 1..4 range                  */
      27                 :             :     AT_RANK       num_defined_parity; /*  number of neighbors with defined parity <= num            */
      28                 :             :     /* AT_RANK       num_undef_parity; */
      29                 :             :     /* AT_RANK       num_unkn_parity;  */
      30                 :             :     AT_RANK       what2do;
      31                 :             :     U_CHAR        cumulene_len;     /*  high nimble bits: (cumulene length - 1)                     */
      32                 :             :     U_CHAR        bond_type;        /*  *2 all same, not a real bond type                           */
      33                 :             : } STEREO_BOND_NEIGH;
      34                 :             : 
      35                 :             : 
      36                 :             : 
      37                 :             : /* Local prototypes */
      38                 :             : 
      39                 :             : int SetHalfStereoBondIllDefPariy( sp_ATOM *at,
      40                 :             :                                   int     jn, /* atom number*/
      41                 :             :                                   int     k1 /* stereo bond number*/,
      42                 :             :                                   int     new_parity );
      43                 :             : 
      44                 :             : int RemoveHalfStereoBond( sp_ATOM *at,
      45                 :             :                           int     jn, /* atom number*/
      46                 :             :                           int     k1 /* stereo bond number*/ );
      47                 :             : 
      48                 :             : int SetKnownStereoBondParities( CANON_GLOBALS *pCG,
      49                 :             :                                 sp_ATOM       *at,
      50                 :             :                                 int           num_atoms,
      51                 :             :                                 const AT_RANK *nCanonRank,
      52                 :             :                                 const AT_RANK *nRank,
      53                 :             :                                 const AT_RANK *nAtomNumber );
      54                 :             : 
      55                 :             : int MarkKnownEqualStereoBondParities( sp_ATOM       *at,
      56                 :             :                                       int           num_atoms,
      57                 :             :                                       const AT_RANK *nRank,
      58                 :             :                                       const AT_RANK *nAtomNumber );
      59                 :             : 
      60                 :             : int GetNextNeighborAndRank( sp_ATOM        *at,
      61                 :             :                             AT_RANK        cur,
      62                 :             :                             AT_RANK        prev,
      63                 :             :                             AT_RANK        *n,
      64                 :             :                             AT_RANK        *cr,
      65                 :             :                             const AT_RANK *nCanonRank );
      66                 :             : 
      67                 :             : int GetAndCheckNextNeighbors( sp_ATOM       *at,
      68                 :             :                               AT_RANK       cur1,
      69                 :             :                               AT_RANK       prev1,
      70                 :             :                               AT_RANK       cur2,
      71                 :             :                               AT_RANK       prev2,
      72                 :             :                               AT_RANK       *n1,
      73                 :             :                               AT_RANK       *n2,
      74                 :             :                               AT_RANK       *nVisited1,
      75                 :             :                               AT_RANK       *nVisited2,
      76                 :             :                               const AT_RANK *nRank,
      77                 :             :                               const AT_RANK *nCanonRank );
      78                 :             : 
      79                 :             : AT_RANK PathsHaveIdenticalKnownParities( sp_ATOM       *at,
      80                 :             :                                          AT_RANK       prev1,
      81                 :             :                                          AT_RANK       cur1,
      82                 :             :                                          AT_RANK       prev2,
      83                 :             :                                          AT_RANK       cur2,
      84                 :             :                                          AT_RANK       *nVisited1,
      85                 :             :                                          AT_RANK       *nVisited2,
      86                 :             :                                          const AT_RANK *nRank,
      87                 :             :                                          const AT_RANK *nCanonRank,
      88                 :             :                                          AT_RANK        nLength );
      89                 :             : 
      90                 :             : int RemoveKnownNonStereoBondParities( sp_ATOM       *at,
      91                 :             :                                       int           num_atoms,
      92                 :             :                                       const AT_RANK *nCanonRank,
      93                 :             :                                       const AT_RANK *nRank,
      94                 :             :                                       CANON_STAT    *pCS );
      95                 :             : 
      96                 :             : int SetKnownStereoCenterParities( CANON_GLOBALS  *pCG,
      97                 :             :                                   sp_ATOM        *at,
      98                 :             :                                   int            num_atoms,
      99                 :             :                                   const AT_RANK  *nCanonRank,
     100                 :             :                                   const AT_RANK  *nRank,
     101                 :             :                                   const AT_RANK  *nAtomNumber );
     102                 :             : int RemoveKnownNonStereoCenterParities( CANON_GLOBALS *pCG,
     103                 :             :                                         sp_ATOM       *at,
     104                 :             :                                         int           num_atoms,
     105                 :             :                                         const AT_RANK *nCanonRank,
     106                 :             :                                         const AT_RANK *nRank,
     107                 :             :                                         CANON_STAT    *pCS );
     108                 :             : 
     109                 :             : int MarkKnownEqualStereoCenterParities( sp_ATOM       *at,
     110                 :             :                                         int           num_atoms,
     111                 :             :                                         const AT_RANK *nRank,
     112                 :             :                                         const AT_RANK *nAtomNumber );
     113                 :             : 
     114                 :             : 
     115                 :             : 
     116                 :             : 
     117                 :             : /****************************************************************************
     118                 :             :   Depth First Search for an atom with parity
     119                 :             : ****************************************************************************/
     120                 :          54 : int find_atoms_with_parity( sp_ATOM *at,
     121                 :             :                             S_CHAR  *visited,
     122                 :             :                             int     from_atom,
     123                 :             :                             int     cur_atom )
     124                 :             : {
     125                 :             :     int i, next_atom;
     126                 :             : 
     127         [ -  + ]:          54 :     if (visited[cur_atom])
     128                 :             :     {
     129                 :           0 :         return 0;
     130                 :             :     }
     131         [ -  + ]:          54 :     if (at[cur_atom].parity)
     132                 :             :     {
     133                 :           0 :         return 1;
     134                 :             :     }
     135                 :             : 
     136                 :          54 :     visited[cur_atom] = 1;
     137                 :             : 
     138         [ +  + ]:         132 :     for (i = 0; i < at[cur_atom].valence; i++)
     139                 :             :     {
     140                 :          78 :         next_atom = at[cur_atom].neighbor[i];
     141                 :             : 
     142   [ +  +  -  + ]:         102 :         if (next_atom != from_atom &&
     143                 :          24 :              find_atoms_with_parity( at, visited, cur_atom, next_atom ))
     144                 :             :         {
     145                 :           0 :             return 1;
     146                 :             :         }
     147                 :             :     }
     148                 :             : 
     149                 :          54 :     return 0;
     150                 :             : }
     151                 :             : 
     152                 :             : 
     153                 :             : /****************************************************************************/
     154                 :           0 : int SetHalfStereoBondIllDefPariy( sp_ATOM *at,
     155                 :             :                                   int     jn, /* atom number*/
     156                 :             :                                   int     k1 /* stereo bond number*/,
     157                 :             :                                   int     new_parity )
     158                 :             : {
     159                 :             :     int parity;
     160   [ #  #  #  # ]:           0 :     if (k1 < MAX_NUM_STEREO_BOND_NEIGH && at[jn].stereo_bond_neighbor[k1])
     161                 :             :     {
     162                 :           0 :         parity = at[jn].stereo_bond_parity[k1] ^ PARITY_VAL( at[jn].stereo_bond_parity[k1] );
     163                 :           0 :         at[jn].stereo_bond_parity[k1] = parity | PARITY_VAL( new_parity );
     164                 :           0 :         at[jn].parity = PARITY_VAL( new_parity );
     165                 :           0 :         return 1;  /*  success */
     166                 :             :     }
     167                 :             : 
     168                 :           0 :     return 0; /*  failed             */
     169                 :             : }
     170                 :             : 
     171                 :             : 
     172                 :             : /****************************************************************************/
     173                 :           0 : int RemoveHalfStereoBond( sp_ATOM *at,
     174                 :             :                           int     jn, /* atom number*/
     175                 :             :                           int     k1 /* stereo bond number*/ )
     176                 :             : {
     177                 :             :     int k2;
     178   [ #  #  #  # ]:           0 :     if (k1 < MAX_NUM_STEREO_BOND_NEIGH && at[jn].stereo_bond_neighbor[k1])
     179                 :             :     {
     180         [ #  # ]:           0 :         for (k2 = k1; k2 < MAX_NUM_STEREO_BOND_NEIGH - 1; k2++) /* djb-rwth: loop condition corrected (buffer error) */
     181                 :             :         {
     182                 :           0 :             at[jn].stereo_bond_neighbor[k2] = at[jn].stereo_bond_neighbor[k2 + 1];
     183                 :           0 :             at[jn].stereo_bond_ord[k2] = at[jn].stereo_bond_ord[k2 + 1];
     184                 :           0 :             at[jn].stereo_bond_z_prod[k2] = at[jn].stereo_bond_z_prod[k2 + 1];
     185                 :           0 :             at[jn].stereo_bond_parity[k2] = at[jn].stereo_bond_parity[k2 + 1];
     186                 :             :         }
     187                 :           0 :         at[jn].stereo_bond_neighbor[k2] = 0;
     188                 :           0 :         at[jn].stereo_bond_ord[k2] = 0;
     189                 :           0 :         at[jn].stereo_bond_z_prod[k2] = 0;
     190                 :           0 :         at[jn].stereo_bond_parity[k2] = 0;
     191                 :             : 
     192         [ #  # ]:           0 :         if (!at[jn].stereo_bond_neighbor[0])
     193                 :             :         {   /*  curled braces added 6-6-2002 */
     194                 :           0 :             at[jn].parity = 0;
     195                 :           0 :             at[jn].stereo_atom_parity = 0;
     196                 :           0 :             at[jn].final_parity = 0;
     197                 :             :             /* at[jn].bHasStereoOrEquToStereo = 0; */
     198                 :             :         }
     199                 :           0 :         return 1; /*  success            */
     200                 :             :     }
     201                 :             : 
     202                 :           0 :     return 0; /*  failed             */
     203                 :             : }
     204                 :             : 
     205                 :             : 
     206                 :             : /****************************************************************************/
     207                 :           0 : int SetOneStereoBondIllDefParity( sp_ATOM *at,
     208                 :             :                                   int     jc,       /* atom number              */
     209                 :             :                                   int     k,        /* stereo bond ord. number  */
     210                 :             :                                   int     new_parity )
     211                 :             : {
     212                 :           0 :     int k1, ret = 0, kn, jn = (int) at[jc].stereo_bond_neighbor[k] - 1;
     213                 :             : 
     214                 :             :     /*  opposite end */
     215                 :           0 :     for (k1 = ret = 0;
     216   [ #  #  #  # ]:           0 :             k1 < MAX_NUM_STEREO_BOND_NEIGH && ( kn = at[jn].stereo_bond_neighbor[k1] );
     217                 :           0 :               k1++) /* djb-rwth: removing redundant code */
     218                 :             :     {
     219         [ #  # ]:           0 :         if (kn - 1 == jc)
     220                 :             :         {
     221                 :           0 :             ret = SetHalfStereoBondIllDefPariy( at, jn, /* atom number*/ k1 /* stereo bond number*/, new_parity );
     222                 :           0 :             break;
     223                 :             :         }
     224                 :             :     }
     225                 :             : 
     226         [ #  # ]:           0 :     if (ret)
     227                 :             :     {
     228                 :           0 :         ret = SetHalfStereoBondIllDefPariy( at, jc, k, new_parity );
     229                 :             :     }
     230                 :             : 
     231                 :           0 :     return ret;
     232                 :             : }
     233                 :             : 
     234                 :             : 
     235                 :             : /****************************************************************************/
     236                 :           0 : int RemoveOneStereoBond( sp_ATOM *at,
     237                 :             :                          int     jc,    /* atom number          */
     238                 :             :                          int     k      /* stereo bond number   */
     239                 :             : )
     240                 :             : {
     241                 :           0 :     int k1, ret = 0, kn, jn = (int) at[jc].stereo_bond_neighbor[k] - 1;
     242                 :             : 
     243                 :             :     /*  opposite end */
     244                 :           0 :     for (k1 = ret = 0;
     245   [ #  #  #  # ]:           0 :             k1 < MAX_NUM_STEREO_BOND_NEIGH && ( kn = at[jn].stereo_bond_neighbor[k1] );
     246                 :           0 :               k1++) /* djb-rwth: removing redundant code */
     247                 :             :     {
     248         [ #  # ]:           0 :         if (kn - 1 == jc)
     249                 :             :         {
     250                 :           0 :             ret = RemoveHalfStereoBond( at, jn, k1 );
     251                 :           0 :             break;
     252                 :             :         }
     253                 :             :     }
     254                 :             : 
     255         [ #  # ]:           0 :     if (ret)
     256                 :             :     {
     257                 :           0 :         ret = RemoveHalfStereoBond( at, jc, k );
     258                 :             :     }
     259                 :             : 
     260                 :           0 :     return ret;
     261                 :             : }
     262                 :             : 
     263                 :             : 
     264                 :             : /****************************************************************************/
     265                 :           0 : int RemoveOneStereoCenter( sp_ATOM *at,
     266                 :             :                            int     jc /* atom number*/ )
     267                 :             : {
     268         [ #  # ]:           0 :     if (at[jc].parity)
     269                 :             :     {
     270                 :           0 :         at[jc].parity = 0; /*  remove parity */
     271                 :           0 :         at[jc].stereo_atom_parity = 0;
     272                 :           0 :         at[jc].final_parity = 0;
     273                 :             :         /*  at[jc].bHasStereoOrEquToStereo = 0; */
     274                 :           0 :         return 1;
     275                 :             :     }
     276                 :             : 
     277                 :           0 :     return 0; /*  failed: not a stereo center */
     278                 :             : }
     279                 :             : 
     280                 :             : 
     281                 :             : /****************************************************************************
     282                 :             :   Remove stereo parity from centers having constitutionally equivalent
     283                 :             :   cut-vertex neighbors whose attachments do not have stereogenic elements.
     284                 :             :   Currently checks ALL constitutionally equivalent neighbors.
     285                 :             :   To optimize, check only one.
     286                 :             : ****************************************************************************/
     287                 :          58 : int UnmarkNonStereo( CANON_GLOBALS *pCG,
     288                 :             :                      sp_ATOM       *at,
     289                 :             :                      int           num_atoms,
     290                 :             :                      const AT_RANK *nRank,
     291                 :             :                      const AT_RANK *nAtomNumber,
     292                 :             :                      int           bIsotopic )
     293                 :             : {
     294                 :             :     int i, i1, i2, j, k, k1, k2, kn /* neigh*/, val, ic/* center*/, jc, num_implicit_H;
     295                 :          58 :     int num_neighbors_with_parity, num_no_parity_atoms, num_removed_parities = -1, num_removed_parities0;
     296                 :             :     AT_RANK nNeighborNumber[MAX_NUM_STEREO_ATOM_NEIGH];
     297                 :             :     AT_RANK nPrevAtomRank, nPrevNeighRank;
     298                 :             : #ifdef FIX_OLEAN_SPIRO_CHIRALITY_DETECTION_BUG
     299                 :          58 :     int num_in_same_ring_system = 1, nRingSystem, num_with_eq_neigh_in_same_ring_system = 0; /* djb-rwth: although unlikely to ever occur, uninitialised num_in_same_ring_system variable can lead to garbage value, including 0 which leads to various errors and inconsistency with 1.06 outputs -- function rewriting and discussion required */
     300                 :             : #endif
     301                 :             : 
     302                 :             : 
     303                 :          58 :     S_CHAR *visited = (S_CHAR *) inchi_malloc( num_atoms * sizeof( visited[0] ) );
     304                 :             : 
     305         [ -  + ]:          58 :     if (!visited)
     306                 :             :     {
     307                 :           0 :         goto exit_function;
     308                 :             :     }
     309                 :             : 
     310                 :          58 :     num_removed_parities = 0;
     311                 :          58 :     num_no_parity_atoms = 0;
     312                 :             : 
     313                 :             :     do
     314                 :             :     {
     315                 :          66 :         num_removed_parities0 = num_removed_parities;
     316                 :             : 
     317         [ +  + ]:         793 :         for (i = i1 = 0, nPrevAtomRank = 0; i <= num_atoms; i++)
     318                 :             :         {
     319                 :             :             /*  bounds violation check (i!=num_atoms) added 6-21-2002 */
     320   [ +  +  +  + ]:         727 :             if (i == num_atoms || nPrevAtomRank != nRank[j = nAtomNumber[i]]
     321                 :             :                  /* at[j].parity && 1 < at[j].valence && at[j].valence < MAX_NUM_STEREO_ATOM_NEIGH*/)
     322                 :             :             {
     323                 :             :                 /*  end of constitutionally equivalent atoms sequence */
     324                 :             :                 /* nPrevRank = nRank[j]; */
     325                 :         666 :                 i2 = i;
     326         [ +  + ]:         666 :                 if (i2 - i1 > num_no_parity_atoms /*&& at[jc = nAtomNumber[i1]].parity*/)
     327                 :             :                 {
     328                 :             :                     /*  at[nAtomNumber[i1]]..at[nAtomNumber[i2-1]] are constitutionally equivalent and some of them have parity */
     329                 :         206 :                     jc = nAtomNumber[i1];
     330                 :         206 :                     num_no_parity_atoms = 0;
     331                 :         206 :                     val = at[jc].valence; /*  all equivalent atoms have equal valences, etc. (except parities) */
     332         [ +  - ]:         206 :                     num_implicit_H = at[jc].endpoint ? 0 : at[jc].num_H;
     333                 :             :                     /*  Only atoms with valence <= MAX_NUM_STEREO_ATOM_NEIGH may have parity. However, check: */
     334         [ -  + ]:         206 :                     if (val + num_implicit_H > MAX_NUM_STEREO_ATOM_NEIGH)
     335                 :             :                     {
     336                 :           0 :                         continue;  /*  program error ??? */ /*   <BRKPT> */
     337                 :             :                     }
     338         [ +  + ]:         824 :                     for (k = 0; k < val; k++)
     339                 :             :                     {
     340                 :         618 :                         nNeighborNumber[k] = k; /*  initialize an array of indexes for sorting */
     341                 :             :                     }
     342                 :             :                     /*  check parities */
     343         [ +  + ]:         415 :                     for (ic = i1; ic < i2; ic++)
     344                 :             :                     {
     345                 :         209 :                         jc = nAtomNumber[ic];
     346                 :             :                         /*  sort neighbors according to their canon. equivalence ranks */
     347                 :         209 :                         pCG->m_pNeighborsForSort = at[jc].neighbor;
     348                 :         209 :                         pCG->m_pn_RankForSort = nRank;
     349                 :         209 :                         insertions_sort( pCG, nNeighborNumber, val, sizeof( nNeighborNumber[0] ), CompNeighborsAT_NUMBER );
     350                 :         209 :                         num_neighbors_with_parity = -1; /*  non-zero */
     351         [ +  - ]:         630 :                         for (k = k1 = 0, nPrevNeighRank = 0; k <= val; k++)
     352                 :             :                         {
     353   [ +  +  +  + ]:         630 :                             if (k == val || nPrevNeighRank != nRank[at[jc].neighbor[nNeighborNumber[k]]])
     354                 :             :                             {
     355                 :         614 :                                 k2 = k;
     356         [ +  + ]:         614 :                                 if (k2 - k1 > 1)
     357                 :             :                                 {
     358                 :             :                                     /*  found 2 or more constitutionally equivalent neighbors */
     359                 :             :                                     /*  Check if they have only non-stereogenic neighbors */
     360                 :             : #ifdef FIX_OLEAN_SPIRO_CHIRALITY_DETECTION_BUG
     361                 :          14 :                                     num_in_same_ring_system = nRingSystem = 0;
     362         [ +  + ]:          44 :                                     for (kn = k1; kn < k2; kn++) /* djb-rwth: removing redundant code */
     363                 :             :                                     {
     364                 :          30 :                                         int nCurNeighRingSystem = at[(int) at[jc].neighbor[nNeighborNumber[kn]]].nRingSystem;
     365         [ +  + ]:          30 :                                         if (!nRingSystem)
     366                 :             :                                         {
     367                 :          14 :                                             nRingSystem = nCurNeighRingSystem;
     368                 :             :                                         }
     369                 :             :                                         else
     370                 :             :                                         {
     371                 :          16 :                                             num_in_same_ring_system += ( nRingSystem == nCurNeighRingSystem );
     372                 :             :                                         }
     373                 :             :                                     }
     374                 :             : #endif
     375                 :             : 
     376         [ +  + ]:          44 :                                     for (kn = k1, num_neighbors_with_parity = 0; kn < k2; kn++)
     377                 :             :                                     {
     378                 :          30 :                                         memset( visited, 0, num_atoms * sizeof( visited[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     379                 :          30 :                                         visited[jc] = 1; /*  starting point; the only atom with parity */
     380                 :          30 :                                         num_neighbors_with_parity +=
     381                 :          30 :                                             find_atoms_with_parity( at, visited, jc, (int) at[jc].neighbor[nNeighborNumber[kn]] );
     382                 :             :                                     }
     383                 :             :                                 }
     384                 :             :                                 /* if ( !num_neighbors_with_parity ) */
     385                 :             : #ifdef FIX_OLEAN_SPIRO_CHIRALITY_DETECTION_BUG
     386   [ +  +  +  - ]:         614 :                                 if (!num_neighbors_with_parity && !num_in_same_ring_system)
     387                 :             : #else
     388                 :             :                                 if (!num_neighbors_with_parity)
     389                 :             : #endif
     390                 :             :                                 {
     391                 :          14 :                                     break; /*  at[jc] cannot have defined parity */
     392                 :             :                                 }
     393         [ +  + ]:         600 :                                 if (k + 1 < val)
     394                 :             :                                 {
     395                 :         405 :                                     k1 = k; /*  at least 2 more neighbors left */
     396                 :         405 :                                     nPrevNeighRank = nRank[at[jc].neighbor[nNeighborNumber[k]]];
     397                 :             :                                 }
     398                 :             :                                 else
     399                 :             :                                 {
     400                 :         195 :                                     break;
     401                 :             :                                 }
     402                 :             :                             }
     403                 :             :                         }
     404         [ -  + ]:         209 :                         if (num_implicit_H > 1)
     405                 :             :                         {
     406   [ #  #  #  # ]:           0 :                             if ((bIsotopic && ( at[jc].num_iso_H[0] > 1 ||
     407         [ #  # ]:           0 :                                 at[jc].num_iso_H[1] > 1 ||
     408   [ #  #  #  # ]:           0 :                                 at[jc].num_iso_H[2] > 1 )) ||
     409         [ #  # ]:           0 :                                   num_implicit_H > NUM_H_ISOTOPES ||
     410                 :             :                                   !bIsotopic) /* djb-rwth: addressing LLVM warning */
     411                 :             :                             {
     412                 :           0 :                                 num_neighbors_with_parity = 0;
     413                 :             :                             }
     414                 :             :                         }
     415                 :             :                         /*  increment if: */
     416                 :             :                         /*  (a) constitutionally equivalent neighbors do exist, and */
     417                 :             :                         /*  (b) all constitutionally equivalent neighbors do not have parity, and */
     418                 :             :                         /*  (c) all constitutionally equivalent neighbors are not connected to atoms with parity */
     419                 :         209 :                         num_no_parity_atoms += !num_neighbors_with_parity;
     420                 :             : #ifdef FIX_OLEAN_SPIRO_CHIRALITY_DETECTION_BUG
     421                 :         209 :                         num_with_eq_neigh_in_same_ring_system += ( num_in_same_ring_system != 0 ); /* djb-rwth: initialisation of num_in_same_ring_system is required to avoid garbage value */
     422                 :             : #endif
     423                 :             :                     }
     424                 :             : #ifdef FIX_OLEAN_SPIRO_CHIRALITY_DETECTION_BUG
     425   [ +  +  +  + ]:         206 :                     if (num_no_parity_atoms == i2 - i1 && num_with_eq_neigh_in_same_ring_system != i2 - i1)
     426                 :             : #else
     427                 :             :                     if (num_no_parity_atoms == i2 - i1)
     428                 :             : #endif
     429                 :             : 
     430                 :             :                     {
     431                 :             :                         /*  all atoms at[nAtomNumber[i1]]..at[nAtomNumber[i2-1]] cannot be */
     432                 :             :                         /*  stereo centers or belong to stereo bonds */
     433         [ +  + ]:          24 :                         for (ic = i1; ic < i2; ic++)
     434                 :             :                         {
     435                 :             :                             int jn;
     436                 :          13 :                             jc = nAtomNumber[ic];
     437                 :          13 :                             at[jc].parity = 0; /*  remove parity */
     438                 :          13 :                             at[jc].stereo_atom_parity = 0;
     439                 :          13 :                             at[jc].final_parity = 0;
     440                 :          13 :                             at[jc].bHasStereoOrEquToStereo = 0;
     441                 :             :                             /*  remove stereo bonds */
     442   [ +  -  -  + ]:          13 :                             for (k = 0; k < MAX_NUM_STEREO_BOND_NEIGH && ( jn = at[jc].stereo_bond_neighbor[k] ); k++)
     443                 :             :                             {
     444                 :           0 :                                 jn--; /*  stereo bond neighbor */
     445                 :             :                                 /*  opposite end */
     446   [ #  #  #  # ]:           0 :                                 for (k1 = 0; k1 < MAX_NUM_STEREO_BOND_NEIGH && ( kn = at[jn].stereo_bond_neighbor[k1] ); k1++)
     447                 :             :                                 {
     448         [ #  # ]:           0 :                                     if (kn - 1 == jc)
     449                 :             :                                     {
     450                 :           0 :                                         RemoveHalfStereoBond( at, jn, k1 );
     451                 :           0 :                                         break;
     452                 :             :                                     }
     453                 :             :                                 }
     454                 :             :                                 /*  at at[jc] stereo bond end; since references to all at[jc] */
     455                 :             :                                 /*  stereo bond neighbors are to be removed, do not shift them */
     456                 :           0 :                                 at[jc].stereo_bond_neighbor[k] = 0;
     457                 :           0 :                                 at[jc].stereo_bond_ord[k] = 0;
     458                 :           0 :                                 at[jc].stereo_bond_z_prod[k] = 0;
     459                 :           0 :                                 at[jc].stereo_bond_parity[k] = 0;
     460                 :             :                             }
     461                 :             :                         }
     462                 :          11 :                         num_removed_parities += num_no_parity_atoms;
     463                 :             :                     }
     464                 :             :                 }
     465         [ +  + ]:         666 :                 if (i < num_atoms)
     466                 :             :                 {
     467                 :         600 :                     nPrevAtomRank = nRank[j];
     468                 :         600 :                     i1 = i;
     469                 :             :                 }
     470                 :         666 :                 num_no_parity_atoms = 0;
     471                 :             :             }
     472   [ +  +  +  + ]:         727 :             num_no_parity_atoms += ( i < num_atoms && !at[j].parity );
     473                 :             :         }
     474                 :             :     }
     475         [ +  + ]:          66 :     while (num_removed_parities != num_removed_parities0);
     476                 :             : 
     477                 :          58 : exit_function:
     478         [ +  - ]:          58 :     if (visited)
     479                 :             :     {
     480         [ +  - ]:          58 :         inchi_free( visited );
     481                 :             :     }
     482                 :             : 
     483                 :          58 :     return num_removed_parities;
     484                 :             : }
     485                 :             : 
     486                 :             : 
     487                 :             : /****************************************************************************
     488                 :             :   Add stereo descriptor(s) for atom #i
     489                 :             : ****************************************************************************/
     490                 :        1168 : int FillSingleStereoDescriptors( CANON_GLOBALS  *pCG,
     491                 :             :                                  sp_ATOM        *at,
     492                 :             :                                  int            i,
     493                 :             :                                  int            num_trans,
     494                 :             :                                  const AT_RANK  *nRank,
     495                 :             :                                  AT_STEREO_CARB *LinearCTStereoCarb,
     496                 :             :                                  int            *nStereoCarbLen,
     497                 :             :                                  int            nMaxStereoCarbLen,
     498                 :             :                                  AT_STEREO_DBLE *LinearCTStereoDble,
     499                 :             :                                  int            *nStereoDbleLen,
     500                 :             :                                  int            nMaxStereoDbleLen,
     501                 :             :                                  int            bAllene )
     502                 :             : {
     503                 :             : 
     504   [ +  -  -  + ]:        1168 :     if (!LinearCTStereoDble && !LinearCTStereoCarb)
     505                 :             :     {
     506                 :           0 :         return 0; /*  return immediately if no stereo have been requested */
     507                 :             :     }
     508                 :             : 
     509                 :             :     /***************************************************
     510                 :             :     add stereo centers and stereo bonds to the CT
     511                 :             :     ***************************************************/
     512   [ +  +  -  + ]:        1168 :     if (at[i].parity || at[i].stereo_bond_neighbor[0])
     513                 :             :     {
     514                 :         376 :         AT_RANK r_neigh, rank = nRank[i];
     515                 :             :         AT_NUMB nNeighborNumber2[MAXVAL];
     516                 :             :         unsigned parity;
     517                 :             :         int      k;
     518                 :         376 :         int num_allene = 0;
     519                 :             : 
     520   [ +  -  +  +  :         376 :         if (ATOM_PARITY_WELL_DEF( at[i].parity ) && num_trans < 0)
                   +  - ]
     521                 :             :         {
     522                 :             :             /*  number of neighbors transpositions to the sorted order is unknown. Find it. */
     523                 :             :             /*  If parity is not well-defined then doing this is a waste of time */
     524                 :         334 :             int num_neigh = at[i].valence;
     525         [ +  + ]:        1336 :             for (k = 0; k < num_neigh; k++)
     526                 :             :             {
     527                 :        1002 :                 nNeighborNumber2[k] = k;
     528                 :             :             }
     529                 :             : 
     530                 :         334 :             pCG->m_pNeighborsForSort = at[i].neighbor;
     531                 :         334 :             pCG->m_pn_RankForSort = nRank;
     532                 :         334 :             num_trans = insertions_sort( pCG, nNeighborNumber2, num_neigh, sizeof( nNeighborNumber2[0] ), CompNeighborsAT_NUMBER );
     533                 :             : 
     534                 :             : #ifndef CT_NEIGH_INCREASE
     535                 :             :             num_trans += ( ( num_neigh*( num_neigh - 1 ) ) / 2 ) % 2;  /*  get correct parity for ascending order */
     536                 :             : #endif
     537                 :             :         }
     538                 :             : 
     539                 :             :         /*  stereo bonds */
     540   [ -  +  -  - ]:         376 :         if (LinearCTStereoDble && at[i].stereo_bond_neighbor[0])
     541                 :             :         {
     542                 :             : 
     543                 :             :             /* HalfStereoBondParity( sp_ATOM *at, int at_no1, int i_sb_neigh, AT_RANK *nRank ) */
     544                 :             :             AT_NUMB nStereoNeighNumber[MAX_NUM_STEREO_BONDS], nStereoNeigh[MAX_NUM_STEREO_BONDS], n;
     545                 :             :             int       num_stereo, stereo_neigh, stereo_neigh_ord, stereo_bond_parity;
     546                 :           0 :             for (num_stereo = 0;
     547         [ #  # ]:           0 :                       num_stereo < MAX_NUM_STEREO_BONDS &&
     548         [ #  # ]:           0 :                       ( n = at[i].stereo_bond_neighbor[num_stereo] ); num_stereo++)
     549                 :             :             {
     550                 :           0 :                 nStereoNeighNumber[num_stereo] = num_stereo;
     551                 :           0 :                 nStereoNeigh[num_stereo] = n - 1;
     552                 :           0 :                 num_allene += IS_ALLENE_CHAIN( at[i].stereo_bond_parity[num_stereo] );
     553                 :             :             }
     554   [ #  #  #  #  :           0 :             if ((bAllene > 0 && !num_allene) || (bAllene == 0 && num_allene)) /* djb-rwth: addressing LLVM warning */
             #  #  #  # ]
     555                 :             :             {
     556                 :           0 :                 return 0;
     557                 :             :             }
     558                 :             : 
     559                 :             :             /*  sort stereo bonds according to the ranks of the neighbors */
     560                 :           0 :             pCG->m_pNeighborsForSort = nStereoNeigh;
     561                 :           0 :             pCG->m_pn_RankForSort = nRank;
     562                 :           0 :             insertions_sort( pCG, nStereoNeighNumber, num_stereo, sizeof( nStereoNeighNumber[0] ), CompNeighborsAT_NUMBER );
     563                 :             : 
     564                 :             :             /*  process stereo bonds one by one */
     565         [ #  # ]:           0 :             for (k = 0; k < num_stereo; k++)
     566                 :             :             {
     567                 :           0 :                 stereo_neigh = nStereoNeigh[stereo_neigh_ord = (int) nStereoNeighNumber[k]];
     568                 :             : 
     569         [ #  # ]:           0 :                 if (( r_neigh = (AT_NUMB) nRank[stereo_neigh] ) CT_NEIGH_SMALLER_THAN rank)
     570                 :             :                 {
     571                 :             :                     /* accept only neighbors that have smaller ranks */
     572                 :           0 :                     stereo_bond_parity = PARITY_VAL( at[i].stereo_bond_parity[stereo_neigh_ord] );
     573         [ #  # ]:           0 :                     if (stereo_bond_parity == AB_PARITY_NONE)
     574                 :             :                     {
     575                 :           0 :                         continue;
     576                 :             :                     }
     577                 :             : 
     578                 :             :                     /* stereo_neigh      = at[i].stereo_bond_neighbor[nStereoNeighNumber[k]]-1; */
     579   [ #  #  #  # ]:           0 :                     if (ATOM_PARITY_KNOWN( stereo_bond_parity ))
     580                 :             :                     {
     581                 :           0 :                         parity = stereo_bond_parity;
     582                 :             :                     }
     583   [ #  #  #  # ]:           0 :                     else if (ATOM_PARITY_WELL_DEF( at[i].parity ) &&
     584   [ #  #  #  # ]:           0 :                               ATOM_PARITY_WELL_DEF( at[stereo_neigh].parity ) &&
     585         [ #  # ]:           0 :                               MIN_DOT_PROD <= abs( at[i].stereo_bond_z_prod[stereo_neigh_ord] ))
     586                 :           0 :                     {
     587                 :             :                         /*  bond parity can be calculated */
     588                 :             :                         int half_parity1, half_parity2, j, nn, stereo_neigh_ord2;
     589                 :           0 :                         stereo_neigh_ord2 = -1;
     590         [ #  # ]:           0 :                         for (j = 0; j < MAX_NUM_STEREO_BONDS &&
     591         [ #  # ]:           0 :                             ( nn = (int) at[stereo_neigh].stereo_bond_neighbor[j] );
     592                 :           0 :                                        j++)
     593                 :             :                         {
     594         [ #  # ]:           0 :                             if (i + 1 == nn)
     595                 :             :                             {
     596                 :             :                                 /* found the opposite end of the stereo bond */
     597                 :           0 :                                 stereo_neigh_ord2 = j;
     598                 :           0 :                                 break;
     599                 :             :                             }
     600                 :             :                         }
     601         [ #  # ]:           0 :                         if (stereo_neigh_ord2 >= 0)
     602                 :             :                         {
     603                 :           0 :                             half_parity1 = HalfStereoBondParity( at, i, stereo_neigh_ord, nRank );
     604                 :           0 :                             half_parity2 = HalfStereoBondParity( at, stereo_neigh, stereo_neigh_ord2, nRank );
     605   [ #  #  #  #  :           0 :                             if (ATOM_PARITY_WELL_DEF( half_parity1 ) &&
                   #  # ]
     606         [ #  # ]:           0 :                                  ATOM_PARITY_WELL_DEF( half_parity2 ))
     607                 :             :                             {
     608                 :           0 :                                 parity = 2 - ( half_parity1 + half_parity2
     609                 :           0 :                                          + ( at[i].stereo_bond_z_prod[stereo_neigh_ord] < 0 ) ) % 2;
     610                 :             :                             }
     611                 :             :                             else
     612                 :             :                             {
     613                 :           0 :                                 return CT_STEREOBOND_ERROR;  /*   <BRKPT> */
     614                 :             :                             }
     615                 :             :                         }
     616                 :             :                         else
     617                 :             :                         {
     618                 :           0 :                             return CT_STEREOBOND_ERROR;  /*   <BRKPT> */
     619                 :             :                         }
     620                 :             :                     }
     621                 :             :                     else
     622                 :             :                     {
     623                 :             :                         /*  parity cannot be calculated: not enough info or 'unknown' */
     624         [ #  # ]:           0 :                         if (AB_PARITY_NONE == ( parity = inchi_max( at[i].parity, at[stereo_neigh].parity ) ))
     625                 :             :                         {
     626                 :           0 :                             continue;
     627                 :             :                         }
     628   [ #  #  #  # ]:           0 :                         if (ATOM_PARITY_WELL_DEF( parity ))
     629                 :             :                         {
     630                 :           0 :                             parity = AB_PARITY_UNDF; /*  should not happen */
     631                 :             :                         }
     632                 :             :                     }
     633         [ #  # ]:           0 :                     if (CHECK_OVERFLOW( *nStereoDbleLen, nMaxStereoDbleLen ))
     634                 :           0 :                         return CT_OVERFLOW;  /*   <BRKPT> */
     635                 :             :                     /*  first stereo bond atom */
     636                 :           0 :                     LinearCTStereoDble[*nStereoDbleLen].at_num1 = rank;
     637                 :             :                     /*  second stereo bond atom (opposite end) */
     638                 :           0 :                     LinearCTStereoDble[*nStereoDbleLen].at_num2 = r_neigh;
     639                 :             :                     /*  bond parity */
     640                 :           0 :                     LinearCTStereoDble[*nStereoDbleLen].parity = parity;
     641                 :           0 :                     ( *nStereoDbleLen )++;
     642                 :             :                 }
     643                 :             :             }
     644                 :             :         }
     645                 :             : 
     646                 :             :         /*  stereo carbon */
     647         [ +  + ]:         376 :         if (bAllene > 0)
     648                 :             :         {
     649                 :         188 :             return 0;
     650                 :             :         }
     651                 :             : 
     652   [ +  -  +  - ]:         188 :         if (LinearCTStereoCarb && !at[i].stereo_bond_neighbor[0])
     653                 :             :         {
     654         [ -  + ]:         188 :             if (CHECK_OVERFLOW( *nStereoCarbLen, nMaxStereoCarbLen ))
     655                 :           0 :                 return CT_OVERFLOW;  /*   <BRKPT> */
     656                 :             :             /*  stereo atom rank */
     657                 :         188 :             LinearCTStereoCarb[*nStereoCarbLen].at_num = rank;
     658                 :             :             /*  stereo atom parity */
     659   [ +  -  +  + ]:         188 :             parity = ATOM_PARITY_WELL_DEF( at[i].parity ) ? ( 2 - ( at[i].parity + num_trans ) % 2 ) : at[i].parity;
     660                 :         188 :             LinearCTStereoCarb[*nStereoCarbLen].parity = parity;
     661                 :         188 :             ( *nStereoCarbLen )++;
     662                 :             :         }
     663                 :             :     }
     664                 :             : 
     665                 :         980 :     return 0;
     666                 :             : }
     667                 :             : 
     668                 :             : 
     669                 :             : /****************************************************************************/
     670                 :           0 : void SwitchAtomStereoAndIsotopicStereo( sp_ATOM *at,
     671                 :             :                                         int     num_atoms,
     672                 :             :                                         int     *bSwitched )
     673                 :             : {
     674                 :             :     int i;
     675                 :             :     /*  switch atom stereo data */
     676         [ #  # ]:           0 :     for (i = 0; i < num_atoms; i++)
     677                 :             :     {
     678                 :           0 :         inchi_swap( (char*) &at[i].parity, (char*) &at[i].parity2, sizeof( at[i].parity ) );
     679                 :           0 :         inchi_swap( (char*) &at[i].final_parity, (char*) &at[i].final_parity2, sizeof( at[i].final_parity ) );
     680                 :           0 :         inchi_swap( (char*) &at[i].stereo_atom_parity, (char*) &at[i].stereo_atom_parity2, sizeof( at[i].stereo_atom_parity ) );
     681                 :           0 :         inchi_swap( (char*) &at[i].bHasStereoOrEquToStereo, (char*) &at[i].bHasStereoOrEquToStereo2, sizeof( at[i].bHasStereoOrEquToStereo ) );
     682                 :             : 
     683                 :           0 :         inchi_swap( (char*) at[i].stereo_bond_neighbor, (char*) at[i].stereo_bond_neighbor2, sizeof( at[i].stereo_bond_neighbor ) );
     684                 :           0 :         inchi_swap( (char*) at[i].stereo_bond_ord, (char*) at[i].stereo_bond_ord2, sizeof( at[i].stereo_bond_ord ) );
     685                 :           0 :         inchi_swap( (char*) at[i].stereo_bond_z_prod, (char*) at[i].stereo_bond_z_prod2, sizeof( at[i].stereo_bond_z_prod ) );
     686                 :           0 :         inchi_swap( (char*) at[i].stereo_bond_parity, (char*) at[i].stereo_bond_parity2, sizeof( at[i].stereo_bond_parity ) );
     687                 :             :     }
     688                 :             : 
     689                 :           0 :     *bSwitched = !*bSwitched;
     690                 :           0 : }
     691                 :             : 
     692                 :             : 
     693                 :             : /****************************************************************************/
     694                 :           0 : void SetCtToIsotopicStereo( CANON_STAT *pCS,
     695                 :             :                             CANON_STAT *pCS2 )
     696                 :             : {
     697                 :           0 :     pCS->LinearCTStereoDble = pCS2->LinearCTIsotopicStereoDble; /*  enable stereo */
     698                 :           0 :     pCS->LinearCTStereoCarb = pCS2->LinearCTIsotopicStereoCarb;
     699                 :             : 
     700                 :           0 :     pCS->LinearCTStereoDbleInv = pCS2->LinearCTIsotopicStereoDbleInv; /*  enable inv. stereo */
     701                 :           0 :     pCS->LinearCTStereoCarbInv = pCS2->LinearCTIsotopicStereoCarbInv;
     702                 :           0 :     pCS->nMaxLenLinearCTStereoDble = pCS2->nMaxLenLinearCTIsotopicStereoDble;
     703                 :           0 :     pCS->nMaxLenLinearCTStereoCarb = pCS2->nMaxLenLinearCTIsotopicStereoCarb;
     704                 :             : 
     705                 :           0 :     pCS->nLenLinearCTStereoDble = pCS2->nLenLinearCTIsotopicStereoDble;
     706                 :           0 :     pCS->nLenLinearCTStereoCarb = pCS2->nLenLinearCTIsotopicStereoCarb;
     707                 :           0 : }
     708                 :             : 
     709                 :             : 
     710                 :             : /****************************************************************************/
     711                 :           0 : void SetCtToNonIsotopicStereo( CANON_STAT *pCS,
     712                 :             :                                CANON_STAT *pCS2 )
     713                 :             : {
     714                 :           0 :     pCS->LinearCTStereoDble = pCS2->LinearCTStereoDble; /*  enable stereo */
     715                 :           0 :     pCS->LinearCTStereoCarb = pCS2->LinearCTStereoCarb;
     716                 :             : 
     717                 :           0 :     pCS->LinearCTStereoDbleInv = pCS2->LinearCTStereoDbleInv; /*  enable inv. stereo */
     718                 :           0 :     pCS->LinearCTStereoCarbInv = pCS2->LinearCTStereoCarbInv;
     719                 :           0 :     pCS->nMaxLenLinearCTStereoDble = pCS2->nMaxLenLinearCTStereoDble;
     720                 :           0 :     pCS->nMaxLenLinearCTStereoCarb = pCS2->nMaxLenLinearCTStereoCarb;
     721                 :             : 
     722                 :           0 :     pCS->nLenLinearCTStereoDble = pCS2->nLenLinearCTStereoDble;
     723                 :           0 :     pCS->nLenLinearCTStereoCarb = pCS2->nLenLinearCTStereoCarb;
     724                 :             : 
     725                 :           0 :     pCS->nLenLinearCTIsotopicStereoDble = pCS2->nLenLinearCTIsotopicStereoDble;
     726                 :           0 :     pCS->nLenLinearCTIsotopicStereoCarb = pCS2->nLenLinearCTIsotopicStereoCarb;
     727                 :           0 : }
     728                 :             : 
     729                 :             : 
     730                 :             : /****************************************************************************/
     731                 :          58 : int FillAllStereoDescriptors( CANON_GLOBALS *pCG,
     732                 :             :                               sp_ATOM       *at,
     733                 :             :                               int           num_atoms,
     734                 :             :                               const         AT_RANK *nCanonRank,
     735                 :             :                               const         AT_RANK *nAtomNumberCanon,
     736                 :             :                               CANON_STAT    *pCS )
     737                 :             : {
     738                 :          58 :     int ret = 0, i;
     739                 :             :     /*  initialize zero lengths */
     740                 :          58 :     pCS->nLenLinearCTStereoCarb = 0;
     741                 :          58 :     pCS->nLenLinearCTStereoDble = 0;
     742                 :             : 
     743                 :             :     /*  fill atom by atom */
     744   [ +  -  +  + ]:         642 :     for (i = 0; !ret && i < num_atoms; i++)
     745                 :             :     {
     746                 :         584 :         ret = FillSingleStereoDescriptors( pCG, at, (int) nAtomNumberCanon[i], -1, nCanonRank
     747                 :             :                           , pCS->LinearCTStereoCarb, &pCS->nLenLinearCTStereoCarb, pCS->nMaxLenLinearCTStereoCarb
     748                 :             :                           , pCS->LinearCTStereoDble, &pCS->nLenLinearCTStereoDble, pCS->nMaxLenLinearCTStereoDble
     749                 :             :                           , 0 /* bAllene */ );
     750                 :             :     }
     751   [ +  -  +  + ]:         642 :     for (i = 0; !ret && i < num_atoms; i++)
     752                 :             :     {
     753                 :         584 :         ret = FillSingleStereoDescriptors( pCG, at, (int) nAtomNumberCanon[i], -1, nCanonRank
     754                 :             :                           , pCS->LinearCTStereoCarb, &pCS->nLenLinearCTStereoCarb, pCS->nMaxLenLinearCTStereoCarb
     755                 :             :                           , pCS->LinearCTStereoDble, &pCS->nLenLinearCTStereoDble, pCS->nMaxLenLinearCTStereoDble
     756                 :             :                           , 1 /* bAllene */ );
     757                 :             :     }
     758                 :             : 
     759                 :          58 :     return ret;
     760                 :             : }
     761                 :             : 
     762                 :             : 
     763                 :             : /****************************************************************************
     764                 :             :  Find stereo bond parities known in advance
     765                 :             : ****************************************************************************/
     766                 :          58 : int SetKnownStereoBondParities( CANON_GLOBALS *pCG,
     767                 :             :                                 sp_ATOM       *at,
     768                 :             :                                 int           num_atoms,
     769                 :             :                                 const AT_RANK *nCanonRank,
     770                 :             :                                 const AT_RANK *nRank,
     771                 :             :                                 const AT_RANK *nAtomNumber )
     772                 :             : {
     773                 :             :     int i, j, n, m, j1, k, num_neigh1, num_neigh2, iMax1, parity;
     774                 :             :     int trans_i1, trans_i2, trans_k1, trans_k2, prev_trans, trans_k, num_set;
     775                 :             :     int i1, i2, k1, k2, n1, n2, m1, m2, /*stereo_bond_parity,*/ cumulene_len;
     776                 :             : 
     777                 :             :     AT_RANK nAtomRank1, nAtomRank2, nAtom1NeighRank;
     778                 :             :     AT_RANK nNeighRank1[MAX_NUM_STEREO_BONDS],
     779                 :             :         nNeighRank2[MAX_NUM_STEREO_BONDS];
     780                 :             :     AT_RANK nNeighCanonRank1[MAX_NUM_STEREO_BONDS],
     781                 :             :         nNeighCanonRank2[MAX_NUM_STEREO_BONDS];
     782                 :             : 
     783         [ +  + ]:         642 :     for (i1 = 0, num_set = 0; i1 < num_atoms; i1++)
     784                 :             :     {
     785   [ +  +  +  - ]:         584 :         if (!at[i1].parity || !at[i1].stereo_bond_neighbor[0])
     786                 :             :         {
     787                 :         584 :             continue;
     788                 :             :         }
     789                 :             : 
     790   [ #  #  #  # ]:           0 :         if (!PARITY_WELL_DEF( at[i1].parity ))
     791                 :             :         {
     792                 :           0 :             continue;
     793                 :             :         }
     794                 :             : 
     795                 :           0 :         nAtomRank1 = nRank[i1];
     796                 :           0 :         iMax1 = (int) nAtomRank1 - 1;
     797                 :           0 :         num_neigh1 = at[i1].valence;
     798                 :             : 
     799         [ #  # ]:           0 :         for (n1 = 0;    n1 < MAX_NUM_STEREO_BONDS &&
     800         [ #  # ]:           0 :             ( i2 = (int) at[i1].stereo_bond_neighbor[n1] );
     801                 :           0 :                            n1++)
     802                 :             :         {
     803                 :           0 :             i2--;
     804                 :             : 
     805                 :             :             /*  found a stereo bond at[i1]-at[i2] adjacent to at[i1] */
     806                 :           0 :             for (n2 = 0, m = 0;
     807                 :           0 :                     n2 < MAX_NUM_STEREO_BONDS &&
     808   [ #  #  #  #  :           0 :                     ( m = (int) at[i2].stereo_bond_neighbor[n2] ) && m - 1 != i1;
                   #  # ]
     809                 :           0 :                         n2++)
     810                 :             :                 ; /* locate stereo bond (#n2) at the opposite atom at[i2] */
     811                 :             : 
     812   [ #  #  #  # ]:           0 :             if (m - 1 != i1 || at[i1].stereo_bond_parity[n1] != at[i2].stereo_bond_parity[n2])
     813                 :             :             {
     814                 :           0 :                 return CT_STEREOCOUNT_ERR; /*  program error */ /*   <BRKPT> */
     815                 :             :             }
     816         [ #  # ]:           0 :             if (i1 < i2)
     817                 :             :             {
     818                 :           0 :                 continue; /* do not process same bond 2 times */
     819                 :             :             }
     820   [ #  #  #  # ]:           0 :             if (PARITY_KNOWN( at[i1].stereo_bond_parity[n1] ) ||
     821         [ #  # ]:           0 :                 !PARITY_VAL( at[i1].stereo_bond_parity[n1] ))
     822                 :             :             {
     823                 :           0 :                 continue;
     824                 :             :             }
     825   [ #  #  #  # ]:           0 :             if (!PARITY_WELL_DEF( at[i1].parity ) ||
     826   [ #  #  #  # ]:           0 :                  !PARITY_WELL_DEF( at[i2].parity ))
     827                 :             :             {
     828                 :           0 :                 continue;
     829                 :             :             }
     830         [ #  # ]:           0 :             if (PARITY_VAL( at[i1].stereo_bond_parity[n1] ) != AB_PARITY_CALC)
     831                 :             :             {
     832                 :           0 :                 continue;  /*  ?? program error ?? should not happen */ /*   <BRKPT> */
     833                 :             :             }
     834                 :             : 
     835                 :             :             /*stereo_bond_parity = PARITY_VAL(at[i1].stereo_bond_parity[n1]);*/
     836                 :           0 :             cumulene_len = BOND_CHAIN_LEN( at[i1].stereo_bond_parity[n1] );
     837                 :           0 :             nAtomRank2 = nRank[i2];
     838                 :           0 :             nAtom1NeighRank = nRank[(int) at[i1].neighbor[(int) at[i1].stereo_bond_ord[n1]]];
     839                 :           0 :             num_neigh2 = at[i2].valence;
     840                 :             : 
     841                 :             :             /*  store ranks of at[i1] stereo bond neighbors except one connected by a stereo bond */
     842                 :           0 :             k = (int) at[i1].stereo_bond_ord[n1];
     843                 :           0 :             trans_i1 = 0;
     844         [ #  # ]:           0 :             for (i = j = 0; i < num_neigh1; i++)
     845                 :             :             {
     846         [ #  # ]:           0 :                 if (i != k)
     847                 :             :                 {
     848                 :           0 :                     nNeighRank1[j] = nRank[(int) at[i1].neighbor[i]];
     849                 :           0 :                     j++;
     850                 :             :                 }
     851                 :             :             }
     852         [ #  # ]:           0 :             if (j == 2)
     853                 :             :             {
     854         [ #  # ]:           0 :                 if (nNeighRank1[0] == nNeighRank1[1])
     855                 :             :                 {
     856                 :             :                     /*  neighbors are constitutionally identical, can't find bond parity */
     857                 :           0 :                     continue;
     858                 :             :                 }
     859                 :           0 :                 trans_i1 = insertions_sort( pCG, nNeighRank1, j, sizeof( nNeighRank1[0] ), comp_AT_RANK );
     860                 :             :             }
     861                 :             : 
     862                 :             :             /*  store ranks of at[i2] stereo bond neighbors except one connected by a stereo bond */
     863                 :           0 :             k = (int) at[i2].stereo_bond_ord[n2];
     864                 :           0 :             trans_i2 = 0;
     865         [ #  # ]:           0 :             for (i = j = 0; i < num_neigh2; i++)
     866                 :             :             {
     867         [ #  # ]:           0 :                 if (i != k)
     868                 :             :                 {
     869                 :           0 :                     nNeighRank2[j] = nRank[(int) at[i2].neighbor[i]];
     870                 :           0 :                     j++;
     871                 :             :                 }
     872                 :             :             }
     873                 :             : 
     874         [ #  # ]:           0 :             if (j == 2)
     875                 :             :             {
     876         [ #  # ]:           0 :                 if (nNeighRank2[0] == nNeighRank2[1])
     877                 :             :                 {
     878                 :             :                     /*  neighbors are constitutionally identical, can't find bond parity */
     879                 :           0 :                     continue;
     880                 :             :                 }
     881                 :           0 :                 trans_i2 = insertions_sort( pCG, nNeighRank2, j, sizeof( nNeighRank2[0] ), comp_AT_RANK );
     882                 :             :             }
     883                 :             : 
     884                 :           0 :             prev_trans = -1;
     885                 :           0 :             trans_k1 = -2; /* djb-rwth: ignoring LLVM warning: value used */
     886                 :           0 :             trans_k = -4; /* 2004-04-28 */
     887                 :             : 
     888                 :             :             /*  find all pairs of atoms that can be mapped on at[i1], at[i2] pair */
     889                 :           0 :             for (j1 = 0;
     890   [ #  #  #  # ]:           0 :                     j1 <= iMax1 && nAtomRank1 == nRank[k1 = (int) nAtomNumber[iMax1 - j1]];
     891                 :           0 :                         j1++)
     892                 :             :             {
     893                 :             :                 /*  at[k1] is constitutionally equivalent to at[i1] */
     894                 :             :                 /*  find all at[k1] neighbors that have rank nAtomRank2; */
     895                 :             :                 /*  then find at[k2] constitutionally equivalent at at[i2] */
     896         [ #  # ]:           0 :                 if (at[k1].valence != num_neigh1)
     897                 :             :                 {
     898                 :           0 :                     return CT_STEREOCOUNT_ERR; /*  program error */ /*   <BRKPT> */
     899                 :             :                 }
     900         [ #  # ]:           0 :                 for (m1 = 0; m1 < num_neigh1; m1++)
     901                 :             :                 {
     902                 :             :                     int prev, next, len;
     903         [ #  # ]:           0 :                     if (nAtom1NeighRank != nRank[k2 = (int) at[k1].neighbor[m1]])
     904                 :             :                     {
     905                 :           0 :                         continue;
     906                 :             :                     }
     907                 :           0 :                     m2 = -1; /*  undefined yet */
     908                 :           0 :                     prev = k1;
     909                 :             :                     /* djb-rwth: removing redundant code */
     910         [ #  # ]:           0 :                     if (cumulene_len)
     911                 :             :                     {
     912         [ #  # ]:           0 :                         for (len = 0, next = (int) at[k1].neighbor[m1]; len < cumulene_len; len++)
     913                 :             :                         {
     914   [ #  #  #  # ]:           0 :                             if (at[next].valence == 2 && !at[next].num_H)
     915                 :             :                             {
     916                 :           0 :                                 j = ( (int) at[next].neighbor[0] == prev );
     917                 :           0 :                                 prev = next;
     918                 :           0 :                                 next = at[next].neighbor[j];
     919                 :             :                             }
     920                 :             :                             else
     921                 :             :                             {
     922                 :             :                                 break; /*  cannot continue */
     923                 :             :                             }
     924                 :             :                         }
     925   [ #  #  #  # ]:           0 :                         if (len != cumulene_len || nAtomRank2 != nRank[next])
     926                 :             :                         {
     927                 :           0 :                             continue;  /*  not found */
     928                 :             :                         }
     929                 :           0 :                         k2 = next;
     930                 :             :                     }
     931         [ #  # ]:           0 :                     if (at[k2].valence != num_neigh2)
     932                 :             :                     {
     933                 :           0 :                         return CT_STEREOCOUNT_ERR; /*  program error */ /*   <BRKPT> */
     934                 :             :                     }
     935                 :             : 
     936                 :             :                     /*  store canon. ranks of at[k1] neighbors */ /*  use i,j,k,m,n */
     937         [ #  # ]:           0 :                     for (n = j = 0; n < num_neigh1; n++)
     938                 :             :                     {
     939         [ #  # ]:           0 :                         if (n != m1)
     940                 :             :                         {
     941                 :           0 :                             i = (int) at[k1].neighbor[n];
     942         [ #  # ]:           0 :                             for (m = 0; m < num_neigh1 - 1; m++)
     943                 :             :                             {
     944         [ #  # ]:           0 :                                 if (nRank[i] == nNeighRank1[m])
     945                 :             :                                 {
     946                 :           0 :                                     nNeighCanonRank1[m] = nCanonRank[i];
     947                 :           0 :                                     j++;
     948                 :           0 :                                     break;
     949                 :             :                                 }
     950                 :             :                             }
     951                 :             :                         }
     952                 :             :                     }
     953         [ #  # ]:           0 :                     if (j != num_neigh1 - 1)
     954                 :             :                     {
     955                 :           0 :                         return CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
     956                 :             :                     }
     957         [ #  # ]:           0 :                     if (j == 2)
     958                 :             :                     {
     959                 :           0 :                         trans_k1 = insertions_sort( pCG, nNeighCanonRank1, j, sizeof( nNeighCanonRank1[0] ), comp_AT_RANK );
     960                 :             :                     }
     961                 :             :                     else
     962                 :             :                     {
     963                 :           0 :                         trans_k1 = 0;
     964                 :             :                     }
     965                 :             : 
     966                 :             :                     /*  store canon. ranks of at[k2] neighbors */ /*  use i,j,k,m,n */
     967         [ #  # ]:           0 :                     for (n = j = 0; n < num_neigh2; n++)
     968                 :             :                     {
     969                 :           0 :                         i = (int) at[k2].neighbor[n];
     970         [ #  # ]:           0 :                         if (i == prev)
     971                 :             :                         {
     972                 :             :                             /* neighbor belongs to the stereobond */
     973                 :           0 :                             m2 = n;
     974                 :             :                         }
     975                 :             :                         else
     976                 :             :                         {
     977         [ #  # ]:           0 :                             for (m = 0; m < num_neigh2 - 1; m++)
     978                 :             :                             {
     979         [ #  # ]:           0 :                                 if (nRank[i] == nNeighRank2[m])
     980                 :             :                                 {
     981                 :           0 :                                     nNeighCanonRank2[m] = nCanonRank[i];
     982                 :           0 :                                     j++;
     983                 :           0 :                                     break;
     984                 :             :                                 }
     985                 :             :                             }
     986                 :             :                         }
     987                 :             :                     }
     988   [ #  #  #  # ]:           0 :                     if (j != num_neigh2 - 1 || m2 < 0)
     989                 :             :                     {
     990                 :           0 :                         return CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
     991                 :             :                     }
     992         [ #  # ]:           0 :                     if (j == 2)
     993                 :             :                     {
     994                 :           0 :                         trans_k2 = insertions_sort( pCG, nNeighCanonRank2, j, sizeof( nNeighCanonRank2[0] ), comp_AT_RANK );
     995                 :             :                     }
     996                 :             :                     else
     997                 :             :                     {
     998                 :           0 :                         trans_k2 = 0;
     999                 :             :                     }
    1000                 :           0 :                     trans_k = ( trans_k1 + trans_k2 ) % 2;
    1001         [ #  # ]:           0 :                     if (prev_trans < 0)
    1002                 :             :                     {
    1003                 :           0 :                         prev_trans = trans_k;
    1004                 :             :                     }
    1005         [ #  # ]:           0 :                     else if (prev_trans != trans_k)
    1006                 :             :                     {
    1007                 :             :                         /* was != trans_k1, changed 9-23-2003 */
    1008                 :           0 :                         break; /*  different number of transpositions */
    1009                 :             :                     }
    1010                 :             :                 } /* end of the second atom mapping cycle */
    1011   [ #  #  #  # ]:           0 :                 if (prev_trans >= 0 && prev_trans != trans_k)
    1012                 :             :                 { /* was != trans_k1, changed 9-23-2003 */
    1013                 :           0 :                     break;
    1014                 :             :                 }
    1015                 :             :             } /* end of the first atom mapping cycle */
    1016                 :             : 
    1017         [ #  # ]:           0 :             if (prev_trans == trans_k)
    1018                 :             :             {
    1019                 :             :                 /* was == trans_k1, changed 9-23-2003 */
    1020                 :             :                 int z_prod;
    1021                 :             : 
    1022                 :             :                 /*  all mappings of canonical numbers on the */
    1023                 :             :                 /*  stereo bond at[i1]-at[i2] produce equivalent numberings. */
    1024                 :             :                 /*  Therefore the stereo bond parity is known at this time. */
    1025                 :             :                 /*  parity_1 = at[i1].parity + (trans_i1 + trans_k1 + num_neigh1 - 1) + (int)at[i1].stereo_bond_ord[n1] */
    1026                 :             :                 /*  expression in parentheses is equivalent to rank[first neigh] > rank[second neigh] */
    1027                 :             :                 /*  same for parity_2. */
    1028                 :             :                 /*  parity_2 = at[i2].parity + (trans_i2 + trans_k2 + num_neigh2 - 1) + (int)at[i2].stereo_bond_ord[n2] */
    1029                 :             :                 /*  Sum of the two parities (without stereo_bond_z_prod) is: */
    1030                 :             : 
    1031                 :           0 :                 parity = ( at[i1].parity + at[i2].parity + prev_trans + trans_i1 + trans_i2
    1032                 :           0 :                               + num_neigh1 + num_neigh2
    1033                 :           0 :                               + (int) at[i1].stereo_bond_ord[n1] + (int) at[i2].stereo_bond_ord[n2] ) % 2;
    1034                 :             : 
    1035                 :           0 :                 z_prod = at[i1].stereo_bond_z_prod[n1];
    1036   [ #  #  #  # ]:           0 :                 if (MIN_DOT_PROD > abs( z_prod ))
    1037                 :             :                 {
    1038                 :           0 :                     parity = AB_PARITY_UNDF; /*  undefined because of geometry */
    1039                 :             :                 }
    1040                 :             :                 else
    1041                 :             :                 {
    1042         [ #  # ]:           0 :                     parity = ( z_prod > 0 ) ? 2 - parity : 1 + parity;
    1043                 :             :                 }
    1044                 :           0 :                 at[i1].stereo_bond_parity[n1] = ALL_BUT_PARITY( at[i1].stereo_bond_parity[n1] ) | parity;
    1045                 :           0 :                 at[i2].stereo_bond_parity[n2] = ALL_BUT_PARITY( at[i2].stereo_bond_parity[n2] ) | parity;
    1046                 :           0 :                 num_set++;
    1047                 :             :             }
    1048                 :             :         }
    1049                 :             :     }
    1050                 :             : 
    1051                 :          58 :     return num_set;
    1052                 :             : }
    1053                 :             : 
    1054                 :             : 
    1055                 :             : /****************************************************************************
    1056                 :             :  Find stereo center parities known in advance
    1057                 :             : ****************************************************************************/
    1058                 :          58 : int MarkKnownEqualStereoBondParities( sp_ATOM       *at,
    1059                 :             :                                       int           num_atoms,
    1060                 :             :                                       const AT_RANK *nRank,
    1061                 :             :                                       const AT_RANK *nAtomNumber )
    1062                 :             : {
    1063                 :             :     int j, n, m, j1, num_neigh1, num_neigh2, iMax1;
    1064                 :             :     int num_set, /*num_sb1, num_sb2,*/ bDifferentParities;
    1065                 :             :     int i1, i2, k1, k2, n1, n2, m1, m2, s1, s2, stereo_bond_parity, stereo_bond_parity2, cumulene_len;
    1066                 :             :     AT_RANK nAtomRank1, nAtomRank2, nAtom1NeighRank, nAtom2NeighRank;
    1067                 :             : 
    1068                 :             :     /* djb-rwth: removing redundant code */
    1069                 :             : 
    1070         [ +  + ]:         642 :     for (i1 = 0, num_set = 0; i1 < num_atoms; i1++)
    1071                 :             :     {
    1072   [ +  +  +  - ]:         584 :         if (!at[i1].parity || !at[i1].stereo_bond_neighbor[0])
    1073                 :             :         {
    1074                 :         584 :             continue;
    1075                 :             :         }
    1076                 :             : 
    1077                 :           0 :         nAtomRank1 = nRank[i1];
    1078                 :           0 :         iMax1 = (int) nAtomRank1 - 1;
    1079                 :           0 :         num_neigh1 = at[i1].valence;
    1080                 :             : 
    1081                 :             :         /*  count stereogenic bonds adjacent to at[i1] */
    1082                 :           0 :         for (n1 = 0;
    1083   [ #  #  #  # ]:           0 :                 n1 < MAX_NUM_STEREO_BONDS && at[i1].stereo_bond_neighbor[n1];
    1084                 :           0 :                     n1++);
    1085                 :             : 
    1086                 :             : 
    1087                 :             :         /*num_sb1 = n1;*/
    1088                 :             :         /*  search for bonds possibly constitutionally equivalent to each of the adjacent bonds */
    1089                 :             :         /*  and find if all of them have same already known parity */
    1090                 :             : 
    1091                 :           0 :         for (n1 = 0;
    1092   [ #  #  #  # ]:           0 :                 n1 < MAX_NUM_STEREO_BONDS && ( i2 = (int) at[i1].stereo_bond_neighbor[n1] );
    1093                 :           0 :                     n1++) /* djb-rwth: removing redundant code */
    1094                 :             :         {
    1095                 :           0 :             i2--;
    1096                 :             : 
    1097                 :           0 :             nAtomRank2 = nRank[i2];
    1098   [ #  #  #  #  :           0 :             if (nAtomRank2 < nAtomRank1 || (nAtomRank2 == nAtomRank1 && i1 < i2)) /* djb-rwth: addressing LLVM warning */
                   #  # ]
    1099                 :             :             {
    1100                 :             :                 /*  An attempt to reduce unnecessary repetitions. */
    1101                 :             :                 /*  We still have repetitions because we do not accumulate a list of */
    1102                 :             :                 /*  processed (nAtomRank2, nAtomRank1) pairs. */
    1103                 :           0 :                 continue;
    1104                 :             :             }
    1105                 :             : 
    1106                 :           0 :             bDifferentParities = -1;   /*  parities have not been compared yet */
    1107                 :             : 
    1108                 :             :             /*  found a stereo bond at[i1]-at[i2] (adjacent to at[i1]) */
    1109                 :             :             /*
    1110                 :             :             if ( !PARITY_KNOWN(at[i1].stereo_bond_parity[n1]) || (at[i1].stereo_bond_parity[n1] & KNOWN_PARITIES_EQL) )
    1111                 :             :             {
    1112                 :             :                 continue;
    1113                 :             :             }
    1114                 :             :             */
    1115         [ #  # ]:           0 :             if (at[i1].stereo_bond_parity[n1] & KNOWN_PARITIES_EQL)
    1116                 :             :             {
    1117                 :           0 :                 continue;
    1118                 :             :             }
    1119                 :             : 
    1120                 :             : 
    1121                 :             :             /*  stereo bond has known or unknown parity; we have not checked it yet */
    1122                 :             : 
    1123                 :           0 :             for (n2 = 0;
    1124   [ #  #  #  # ]:           0 :                  n2 < MAX_NUM_STEREO_BONDS && at[i2].stereo_bond_neighbor[n2];
    1125                 :           0 :                  n2++)
    1126                 :             :             {
    1127                 :             :                 ;
    1128                 :             :             }
    1129                 :             : 
    1130                 :             :             /*num_sb2 = n2;*/
    1131                 :           0 :             for (n2 = 0, m = 0;
    1132                 :           0 :                  n2 < MAX_NUM_STEREO_BONDS &&
    1133   [ #  #  #  # ]:           0 :                  ( m = (int) at[i2].stereo_bond_neighbor[n2] ) &&
    1134         [ #  # ]:           0 :                     m - 1 != i1;
    1135                 :           0 :                  n2++)
    1136                 :             :             {
    1137                 :             :                 ;
    1138                 :             :             }
    1139                 :             : 
    1140   [ #  #  #  # ]:           0 :             if (m - 1 != i1 || at[i1].stereo_bond_parity[n1] != at[i2].stereo_bond_parity[n2])
    1141                 :             :             {
    1142                 :           0 :                 return CT_STEREOCOUNT_ERR; /*  program error: stereo bonds data in two directions are different */ /*   <BRKPT> */
    1143                 :             :             }
    1144                 :             : 
    1145                 :           0 :             stereo_bond_parity = PARITY_VAL( at[i1].stereo_bond_parity[n1] );
    1146                 :           0 :             cumulene_len = BOND_CHAIN_LEN( at[i1].stereo_bond_parity[n1] );
    1147                 :           0 :             nAtom1NeighRank = nRank[(int) at[i1].neighbor[(int) at[i1].stereo_bond_ord[n1]]];
    1148                 :           0 :             nAtom2NeighRank = nRank[(int) at[i2].neighbor[(int) at[i2].stereo_bond_ord[n2]]];
    1149                 :           0 :             num_neigh2 = at[i2].valence;
    1150                 :             : 
    1151                 :             :             /*  find all pairs of atoms that possibly can be mapped on at[i1], at[i2] pair */
    1152                 :             :             /*  (we may also find pairs that cannot be mapped, but we cannot miss any pair */
    1153                 :             :             /*  that can be mapped) */
    1154                 :             : 
    1155   [ #  #  #  # ]:           0 :             for (j1 = 0; j1 <= iMax1 && nAtomRank1 == nRank[k1 = (int) nAtomNumber[iMax1 - j1]]; j1++)
    1156                 :             :             {
    1157                 :             :                 /*  at[k1] is constitutionally equivalent to at[i1] */
    1158                 :             :                 /*  find all at[k1] stereo bond neighbors at[k2] that have rank nAtomRank2; */
    1159                 :             :                 /*  then find at[k2] constitutionally equivalent at at[i2] */
    1160                 :             : 
    1161         [ #  # ]:           0 :                 if (at[k1].valence != num_neigh1)
    1162                 :             :                 {
    1163                 :           0 :                     return CT_STEREOCOUNT_ERR; /*  program error */ /*   <BRKPT> */
    1164                 :             :                 }
    1165                 :             : 
    1166         [ #  # ]:           0 :                 if (!at[k1].bHasStereoOrEquToStereo)
    1167                 :             :                 {
    1168                 :           0 :                     at[k1].bHasStereoOrEquToStereo = 1;
    1169                 :             :                 }
    1170                 :             : 
    1171                 :             :                 /* -- do not check number of stereo bonds, check bonds themselves --
    1172                 :             :                 for ( s1 = 0; s1 < MAX_NUM_STEREO_BONDS && at[k1].stereo_bond_neighbor[s1]; s1++ )
    1173                 :             :                 {
    1174                 :             :                     ;
    1175                 :             :                 }
    1176                 :             :                 if ( num_sb1 != s1 )
    1177                 :             :                 {
    1178                 :             :                     bDifferentParities = 1;
    1179                 :             :                 }
    1180                 :             :                 */
    1181                 :             : 
    1182         [ #  # ]:           0 :                 for (m1 = 0; m1 < num_neigh1; m1++)
    1183                 :             :                 {
    1184                 :             :                     /*  Looking for at[k1] neighbor with nRank=nAtom1NeighRank. */
    1185                 :             :                     /*  This neighbor may be on the bond constit. equivalent to at[i1]-at[i2] stereo bond */
    1186                 :             :                     /*  (or may be constit. equivalent an adjacent to at[i1] atom in a stereogenic cumulene chain) */
    1187                 :             :                     int prev, next, len;
    1188         [ #  # ]:           0 :                     if (nAtom1NeighRank != nRank[k2 = (int) at[k1].neighbor[m1]])
    1189                 :           0 :                         continue;
    1190                 :             : 
    1191                 :             :                     /*  found at[k1] neighbor with nRank=nAtom1NeighRank */
    1192                 :             : 
    1193                 :           0 :                     m2 = -1; /*  undefined yet */
    1194                 :           0 :                     prev = k1;
    1195                 :             :                     /* djb-rwth: removing redundant code */
    1196                 :             : 
    1197                 :             :                     /*  if cumulene then bypass the cumulene chain */
    1198                 :             : 
    1199         [ #  # ]:           0 :                     if (cumulene_len)
    1200                 :             :                     {
    1201                 :             : 
    1202         [ #  # ]:           0 :                         for (len = 0, next = (int) at[k1].neighbor[m1]; len < cumulene_len; len++)
    1203                 :             :                         {
    1204   [ #  #  #  # ]:           0 :                             if (at[next].valence == 2 && !at[next].num_H)
    1205                 :             :                             {
    1206                 :           0 :                                 j = ( (int) at[next].neighbor[0] == prev );
    1207                 :           0 :                                 prev = next;
    1208                 :           0 :                                 next = at[next].neighbor[j];
    1209                 :             :                             }
    1210                 :             :                             else
    1211                 :             :                             {
    1212                 :             :                                 break; /*  cannot continue: end of cumulene chain */
    1213                 :             :                             }
    1214                 :             :                         }
    1215                 :             : 
    1216   [ #  #  #  # ]:           0 :                         if (len != cumulene_len || nAtomRank2 != nRank[next])
    1217                 :             :                         {
    1218                 :           0 :                             continue;  /*  cumulene chain not found at this neighbor */
    1219                 :             :                         }
    1220                 :             : 
    1221         [ #  # ]:           0 :                         if (nAtom2NeighRank != nRank[prev])
    1222                 :             :                         {
    1223                 :             :                             /* continue; */ /*  ??? program error ??? If not, must be a very rare event */
    1224                 :           0 :                             return CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
    1225                 :             :                         }
    1226                 :             : 
    1227                 :           0 :                         k2 = next;
    1228                 :             :                     }
    1229                 :             : 
    1230                 :             :                     /*  a connected pair of constit. equivalent atoms found */
    1231                 :             : 
    1232         [ #  # ]:           0 :                     if (at[k2].valence != num_neigh2)
    1233                 :             :                     {
    1234                 :           0 :                         return CT_STEREOCOUNT_ERR; /*  program error */ /*   <BRKPT> */
    1235                 :             :                     }
    1236                 :             : 
    1237         [ #  # ]:           0 :                     for (n = 0; n < num_neigh2; n++)
    1238                 :             :                     {
    1239         [ #  # ]:           0 :                         if (prev == (int) at[k2].neighbor[n])
    1240                 :             :                         {
    1241                 :           0 :                             m2 = n; /*  found bond from the opposite end of a possibly stereogenic bond */
    1242                 :           0 :                             break;
    1243                 :             :                         }
    1244                 :             :                     }
    1245                 :             : 
    1246         [ #  # ]:           0 :                     if (m2 < 0)
    1247                 :             :                     {
    1248                 :           0 :                         return CT_STEREOCOUNT_ERR; /*  program error: opposite direction bond not found */ /*   <BRKPT> */
    1249                 :             :                     }
    1250                 :             : 
    1251         [ #  # ]:           0 :                     if (!at[k2].bHasStereoOrEquToStereo)
    1252                 :             :                     {
    1253                 :           0 :                         at[k2].bHasStereoOrEquToStereo = 1;
    1254                 :             :                     }
    1255                 :             : 
    1256                 :             : 
    1257                 :             :                     /*  check if atoms at[k1] and at[k2] are connected by a stereo bond */
    1258                 :           0 :                     for (s1 = 0, m = 0;
    1259                 :           0 :                          s1 < MAX_NUM_STEREO_BONDS &&
    1260   [ #  #  #  # ]:           0 :                          ( m = (int) at[k1].stereo_bond_neighbor[s1] ) &&
    1261         [ #  # ]:           0 :                                     m - 1 != k2;
    1262                 :           0 :                          s1++)
    1263                 :             :                     {
    1264                 :             :                         ;
    1265                 :             :                     }
    1266         [ #  # ]:           0 :                     if (m - 1 != k2)
    1267                 :             :                     {
    1268                 :           0 :                         bDifferentParities = 1; /*  cannot find the stereo bond */
    1269                 :           0 :                         at[k1].bHasStereoOrEquToStereo =
    1270                 :           0 :                             at[k2].bHasStereoOrEquToStereo = 2;
    1271                 :           0 :                         continue;
    1272                 :             :                     }
    1273                 :             : 
    1274                 :             :                     /*  -- do not check number of stereo bonds, check bonds themselves --
    1275                 :             :                     for ( s2 = 0; s2 < MAX_NUM_STEREO_BONDS && at[k2].stereo_bond_neighbor[s2]; s2++ )
    1276                 :             :                      {
    1277                 :             :                         ;
    1278                 :             :                      }
    1279                 :             :                     if ( num_sb2 != s2 )
    1280                 :             :                     {
    1281                 :             :                         bDifferentParities = 1;
    1282                 :             :                         continue;
    1283                 :             :                     }
    1284                 :             :                     */
    1285                 :             : 
    1286                 :           0 :                     for (s2 = 0, m = 0;
    1287                 :           0 :                          s2 < MAX_NUM_STEREO_BONDS &&
    1288   [ #  #  #  # ]:           0 :                          ( m = (int) at[k2].stereo_bond_neighbor[s2] ) &&
    1289         [ #  # ]:           0 :                                     m - 1 != k1;
    1290                 :           0 :                          s2++)
    1291                 :             :                     {
    1292                 :             :                         ;
    1293                 :             :                     }
    1294                 :             : 
    1295         [ #  # ]:           0 :                     if (m - 1 != k1)
    1296                 :             :                     {
    1297                 :             :                         /*
    1298                 :             :                         bDifferentParities = 1; // cannot find the stereo bond
    1299                 :             :                         continue;
    1300                 :             :                         */
    1301                 :           0 :                         return CT_STEREOCOUNT_ERR; /*  program error: opposite direction bond not found */ /*   <BRKPT> */
    1302                 :             :                     }
    1303                 :             : 
    1304         [ #  # ]:           0 :                     if (at[k1].stereo_bond_parity[s1] != at[k2].stereo_bond_parity[s2])
    1305                 :             :                     {
    1306                 :           0 :                         bDifferentParities = 1;
    1307                 :           0 :                         continue;
    1308                 :             :                     }
    1309                 :           0 :                     stereo_bond_parity2 = PARITY_VAL( at[k1].stereo_bond_parity[s1] );
    1310         [ #  # ]:           0 :                     if (stereo_bond_parity2 != stereo_bond_parity)
    1311                 :             :                     {
    1312                 :           0 :                         bDifferentParities = 1;
    1313                 :           0 :                         continue;
    1314                 :             :                     }
    1315   [ #  #  #  # ]:           0 :                     if (stereo_bond_parity2 == stereo_bond_parity && bDifferentParities < 0)
    1316                 :             :                     {
    1317                 :           0 :                         bDifferentParities = 0;
    1318                 :             :                     }
    1319                 :             :                 }
    1320                 :             :             }
    1321                 :             : 
    1322                 :             :             /*  mark equal parities */
    1323   [ #  #  #  #  :           0 :             if (0 == bDifferentParities && PARITY_KNOWN( stereo_bond_parity ))
                   #  # ]
    1324                 :             :             {
    1325                 :           0 :                 for (j1 = 0;
    1326   [ #  #  #  # ]:           0 :                         j1 <= iMax1 && nAtomRank1 == nRank[k1 = (int) nAtomNumber[iMax1 - j1]];
    1327                 :           0 :                             j1++)
    1328                 :             :                 {
    1329                 :             :                     /*  at[k1] is constitutionally equivalent to at[i1] */
    1330   [ #  #  #  # ]:           0 :                     for (s1 = 0; s1 < MAX_NUM_STEREO_BONDS && ( k2 = (int) at[k1].stereo_bond_neighbor[s1] ); s1++) /* djb-rwth: removing redundant code */
    1331                 :             :                     {
    1332                 :           0 :                         k2--;
    1333         [ #  # ]:           0 :                         if (nRank[k2] == nAtomRank2)
    1334                 :             :                         {
    1335                 :             :                             int b1, b2;
    1336                 :           0 :                             for (s2 = 0, m = 0;
    1337                 :           0 :                                  s2 < MAX_NUM_STEREO_BONDS &&
    1338   [ #  #  #  # ]:           0 :                                     ( m = (int) at[k2].stereo_bond_neighbor[s2] ) &&
    1339         [ #  # ]:           0 :                                     m - 1 != k1;
    1340                 :           0 :                                  s2++)
    1341                 :             :                             {
    1342                 :             :                                 ;
    1343                 :             :                             }
    1344                 :             : 
    1345         [ #  # ]:           0 :                             if (m - 1 != k1)
    1346                 :             :                             {
    1347                 :           0 :                                 return CT_STEREOCOUNT_ERR; /*  program error */ /*   <BRKPT> */
    1348                 :             :                             }
    1349                 :             :                             /*  mark the stereo bonds */
    1350                 :           0 :                             b1 = !( at[k1].stereo_bond_parity[s1] & KNOWN_PARITIES_EQL );
    1351                 :           0 :                             b2 = !( at[k2].stereo_bond_parity[s2] & KNOWN_PARITIES_EQL );
    1352         [ #  # ]:           0 :                             if (2 == b1 + b2)
    1353                 :             :                             {
    1354                 :           0 :                                 at[k1].stereo_bond_parity[s1] |= KNOWN_PARITIES_EQL;
    1355                 :           0 :                                 at[k2].stereo_bond_parity[s2] |= KNOWN_PARITIES_EQL;
    1356                 :           0 :                                 num_set++;
    1357                 :             :                             }
    1358   [ #  #  #  # ]:           0 :                             else if (b1 || b2)
    1359                 :             :                             {
    1360                 :           0 :                                 return CT_STEREOCOUNT_ERR; /*  program error */ /*   <BRKPT> */
    1361                 :             :                             }
    1362                 :             :                         }
    1363                 :             :                     }
    1364                 :             :                 }
    1365                 :             :             }
    1366                 :             :         }
    1367                 :             :     }
    1368                 :             : 
    1369                 :          58 :     return num_set;
    1370                 :             : }
    1371                 :             : 
    1372                 :             : 
    1373                 :             : 
    1374                 :             : #if ( REMOVE_KNOWN_NONSTEREO == 1 ) /* { */
    1375                 :             : 
    1376                 :             : 
    1377                 :             : /****************************************************************************
    1378                 :             :  Return next atom number (and its canon. rank) on the path prev->cur->next
    1379                 :             :  in order of ascending canonical ranks of the next atoms:
    1380                 :             :     *cr(output) >  *cr(input)
    1381                 :             :  To start the sequence let *cr=0
    1382                 :             :  If no more neighbors available the return value = 0; on success, returns 1.
    1383                 :             : ****************************************************************************/
    1384                 :           8 : int GetNextNeighborAndRank( sp_ATOM       *at,
    1385                 :             :                             AT_RANK       cur,
    1386                 :             :                             AT_RANK       prev,
    1387                 :             :                             AT_RANK       *n,
    1388                 :             :                             AT_RANK       *cr,
    1389                 :             :                             const AT_RANK *nCanonRank )
    1390                 :             : {
    1391                 :             :     int i, val;
    1392                 :           8 :     AT_RANK cr1 = MAX_ATOMS + 1, j, j1 = MAX_ATOMS + 1, crj;
    1393                 :             : 
    1394         [ +  + ]:          24 :     for (i = 0, val = at[(int) cur].valence; i < val; i++)
    1395                 :             :     {
    1396         [ +  + ]:          16 :         if (( j = at[cur].neighbor[i] ) != prev &&
    1397   [ +  -  +  - ]:           8 :              cr1 > ( crj = nCanonRank[(int) j] ) && crj > *cr)
    1398                 :             :         {
    1399                 :           8 :             cr1 = crj;
    1400                 :           8 :             j1 = j;
    1401                 :             :         }
    1402                 :             :     }
    1403         [ +  - ]:           8 :     if (cr1 <= MAX_ATOMS)
    1404                 :             :     {
    1405                 :           8 :         *cr = cr1;
    1406                 :           8 :         *n = (AT_RANK) j1;
    1407                 :           8 :         return 1;
    1408                 :             :     }
    1409                 :             : 
    1410                 :           0 :     return 0;  /*  program error */ /*   <BRKPT> */
    1411                 :             : }
    1412                 :             : 
    1413                 :             : 
    1414                 :             : /****************************************************************************
    1415                 :             :  Find next pair of neighbors having the next greater canon. rank
    1416                 :             :  The neighbors should be constitutionally identical and traversed
    1417                 :             :  simultaneouslyor not traversed at all
    1418                 :             :  If a bond cur1-*n1 or cur2-*n2 is a stereo bond then reject if their stereo
    1419                 :             :  bond parities are different or cannot be calculated without breaking ties.
    1420                 :             : ****************************************************************************/
    1421                 :           4 : int GetAndCheckNextNeighbors( sp_ATOM       *at,
    1422                 :             :                               AT_RANK       cur1,
    1423                 :             :                               AT_RANK       prev1,
    1424                 :             :                               AT_RANK       cur2,
    1425                 :             :                               AT_RANK       prev2,
    1426                 :             :                               AT_RANK       *n1,
    1427                 :             :                               AT_RANK       *n2,
    1428                 :             :                               AT_RANK       *nVisited1,
    1429                 :             :                               AT_RANK       *nVisited2,
    1430                 :             :                               const AT_RANK *nRank,
    1431                 :             :                               const AT_RANK *nCanonRank )
    1432                 :             : {
    1433                 :             :     AT_RANK cr1, cr2, s1, s2;
    1434                 :             :     int     i1, i2, k1, k2;
    1435                 :             : 
    1436         [ -  + ]:           4 :     cr1 = ( *n1 > MAX_ATOMS ) ? 0 : nCanonRank[(int) *n1];
    1437         [ -  + ]:           4 :     cr2 = ( *n2 > MAX_ATOMS ) ? 0 : nCanonRank[(int) *n2];
    1438                 :             : 
    1439   [ +  -  +  - ]:           8 :     if (!GetNextNeighborAndRank( at, cur1, prev1, n1, &cr1, nCanonRank ) ||
    1440                 :           4 :          !GetNextNeighborAndRank( at, cur2, prev2, n2, &cr2, nCanonRank ) ||
    1441   [ +  -  -  + ]:           4 :          nRank[(int) *n1] != nRank[(int) *n2] || nVisited1[(int) *n1] != nVisited2[(int) *n2])
    1442                 :             :     {
    1443                 :           0 :         return 0;  /*  program error; no breakpoint here */ /*   <BRKPT> */
    1444                 :             :     }
    1445                 :             : 
    1446                 :             :     /*  Even though the bond or cumulene might have already been checked, check it: this is */
    1447                 :             :     /*  the only place we can check stereo bonds and cumulenes that are not edges of the DFS tree */
    1448                 :             :     /*  The code works both for a stereo bond and a stereogenic cumulene. */
    1449                 :           4 :     for (i1 = 0, k1 = 0;
    1450                 :           4 :          i1 < MAX_NUM_STEREO_BONDS &&
    1451   [ +  -  -  + ]:           4 :          ( s1 = at[cur1].stereo_bond_neighbor[i1] ) &&
    1452         [ #  # ]:           0 :             !( k1 = ( at[cur1].neighbor[(int) at[cur1].stereo_bond_ord[i1]] == *n1 ) );
    1453                 :           0 :          i1++) /* djb-rwth: ignoring LLVM warning: variable used */
    1454                 :             :     {
    1455                 :             :         ;
    1456                 :             :     }
    1457                 :             : 
    1458                 :           4 :     for (i2 = 0, k2 = 0;
    1459                 :           4 :          i2 < MAX_NUM_STEREO_BONDS &&
    1460   [ +  -  -  + ]:           4 :          ( s2 = at[cur2].stereo_bond_neighbor[i2] ) &&
    1461         [ #  # ]:           0 :             !( k2 = ( at[cur2].neighbor[(int) at[cur2].stereo_bond_ord[i2]] == *n2 ) );
    1462                 :           0 :          i2++) /* djb-rwth: ignoring LLVM warning: variable used */
    1463                 :             :     {
    1464                 :             :         ;
    1465                 :             :     }
    1466                 :             : 
    1467         [ -  + ]:           4 :     if (k1 != k2)
    1468                 :             :     {
    1469                 :           0 :         return 0; /*  possibly not an error: constit. equivalent atoms on a stereo bond and not on a stereo bond */
    1470                 :             :     }
    1471                 :             : 
    1472         [ -  + ]:           4 :     if (k1 /* yes, it is a stereo bond */ &&
    1473         [ #  # ]:           0 :         ( at[cur1].stereo_bond_parity[i1] != at[cur2].stereo_bond_parity[i2] ||
    1474                 :             :           /* PARITY_KNOWN (at[cur1].stereo_bond_parity[i1] ) */  /*  replaced 08-13-2002 with the next: */
    1475   [ #  #  #  # ]:           0 :             !PARITY_WELL_DEF( at[cur1].stereo_bond_parity[i1] ) /*  it suffices to check only one parity */
    1476                 :             :             ))
    1477                 :             :     {
    1478                 :           0 :         return 0; /*  different or (currently) unknown stereo bond parities */
    1479                 :             :     }
    1480                 :             : 
    1481                 :           4 :     return 1; /*  stereo bonds have known parities */
    1482                 :             : }
    1483                 :             : 
    1484                 :             : 
    1485                 :             : /********************************************************************************************/
    1486                 :             : /*  Simultaneously DFS-traverse 2 paths starting at the bonds prev1->cur1 and prev2->cur2   */
    1487                 :             : /*  The two paths MUST go through the pairs of constitutionally identical atoms,            */
    1488                 :             : /*  each atom being on one path.                                                            */
    1489                 :             : /*  Reject if encountered atoms having currently unknown (without breaking ties)            */
    1490                 :             : /*      parities or having different known or unknown or undefined parities.                */
    1491                 :             : /*  Save length of the path into nVisited[cur. atom number].                                */
    1492                 :             : /*  Only one nVisited[] array is sufficient because the paths from the beginning are        */
    1493                 :             : /*  in different ring systems.                                                              */
    1494                 :             : /********************************************************************************************/
    1495                 :           3 : AT_RANK PathsHaveIdenticalKnownParities( sp_ATOM       *at,
    1496                 :             :                                          AT_RANK       prev1,
    1497                 :             :                                          AT_RANK       cur1,
    1498                 :             :                                          AT_RANK       prev2,
    1499                 :             :                                          AT_RANK       cur2,
    1500                 :             :                                          AT_RANK       *nVisited1,
    1501                 :             :                                          AT_RANK       *nVisited2,
    1502                 :             :                                          const AT_RANK *nRank,
    1503                 :             :                                          const AT_RANK *nCanonRank,
    1504                 :             :                                          AT_RANK       nLength )
    1505                 :             : {
    1506                 :             :     int k;
    1507                 :             :     AT_RANK n1, n2;
    1508                 :             : 
    1509                 :           3 :     nLength++;   /*  number of successfully traversed pairs of atoms */
    1510                 :           3 :     nVisited1[cur1] = nLength;
    1511                 :           3 :     nVisited2[cur2] = nLength;
    1512                 :             : 
    1513                 :             :     /*  the atoms must be either both stereogenic and have well-defined parities or non-stereogenic at all. */
    1514         [ +  - ]:           3 :     if (at[cur1].stereo_atom_parity != at[cur2].stereo_atom_parity ||
    1515   [ -  +  -  -  :           3 :          (at[cur1].stereo_atom_parity && !PARITY_WELL_DEF( at[cur1].stereo_atom_parity )) ) /* djb-rwth: addressing LLVM warning */
                   -  - ]
    1516                 :             :     {
    1517                 :           0 :         return 0;  /*  Reject: Different or unknown in advance parities */
    1518                 :             :     }
    1519                 :             : 
    1520         [ -  + ]:           3 :     if (at[cur1].valence != at[cur2].valence)
    1521                 :             :     {
    1522                 :           0 :         return 0;  /*  program error */ /*   <BRKPT> */
    1523                 :             :     }
    1524                 :             : 
    1525         [ +  + ]:           3 :     if (at[cur1].valence == 1)
    1526                 :             :     {
    1527                 :           1 :         return nLength; /*  so far success */
    1528                 :             :     }
    1529                 :             : 
    1530                 :             : 
    1531         [ +  + ]:           4 :     for (k = 1, n1 = MAX_ATOMS + 1, n2 = MAX_ATOMS + 1; k < at[cur1].valence; k++)
    1532                 :             :     {
    1533                 :             :         /*  start from 1: since we do not go back, we have only (at[cur1].valence-1) bonds to try */
    1534                 :             : 
    1535         [ -  + ]:           2 :         if (!GetAndCheckNextNeighbors( at, cur1, prev1, cur2, prev2,
    1536                 :             :             &n1, &n2, nVisited1, nVisited2,
    1537                 :             :             nRank, nCanonRank ))
    1538                 :             :         {
    1539                 :           0 :             return 0; /*  different neighbors                       */
    1540                 :             :         }
    1541                 :             : 
    1542                 :             :         /*  In a DFS we do not traverse already visited atoms */
    1543         [ +  - ]:           2 :         if (!nVisited1[n1])
    1544                 :             :         {
    1545                 :             :             /*  recursion */
    1546         [ -  + ]:           2 :             if (!( nLength = PathsHaveIdenticalKnownParities( at, cur1, n1, cur2, n2, nVisited1, nVisited2, nRank, nCanonRank, nLength ) ))
    1547                 :             :             {
    1548                 :           0 :                 return 0;
    1549                 :             :             }
    1550                 :             :         }
    1551                 :             :     }
    1552                 :             : 
    1553                 :             :     /*  To be on a safe side, recheck after all nVisited[] have been set */
    1554         [ +  + ]:           4 :     for (k = 1, n1 = MAX_ATOMS + 1, n2 = MAX_ATOMS + 1; k < at[cur1].valence; k++)
    1555                 :             :     {
    1556                 :             :         /*  start from 1: since we do not go back, we have only (at[cur1].valence-1) bonds to try */
    1557         [ -  + ]:           2 :         if (!GetAndCheckNextNeighbors( at, cur1, prev1, cur2, prev2,
    1558                 :             :             &n1, &n2, nVisited1, nVisited2,
    1559                 :             :             nRank, nCanonRank ))
    1560                 :             :         {
    1561                 :           0 :             return 0; /*  different neighbors */
    1562                 :             :         }
    1563                 :             :     }
    1564                 :             : 
    1565                 :           2 :     return nLength;
    1566                 :             : }
    1567                 :             : 
    1568                 :             : 
    1569                 :             : /****************************************************************************/
    1570                 :             : /*  Remove stereo marks from the bonds that are known to be non-stereo      */
    1571                 :             : /*  (compare neighbors if they are attached by cut-edges)                   */
    1572                 :             : /****************************************************************************/
    1573                 :          59 : int RemoveKnownNonStereoBondParities( sp_ATOM       *at,
    1574                 :             :                                       int           num_atoms,
    1575                 :             :                                       const AT_RANK *nCanonRank,
    1576                 :             :                                       const AT_RANK *nRank,
    1577                 :             :                                       CANON_STAT    *pCS )
    1578                 :             : {
    1579                 :             :     int j, n, m, ret;
    1580                 :             : 
    1581                 :             :     int i1, n1, s2;
    1582                 :          59 :     AT_RANK nAtomRank1, nAtomRank2, neigh[3], opposite_atom, *nVisited = NULL;
    1583                 :          59 :     ret = 0;
    1584         [ +  + ]:         656 :     for (i1 = 0; i1 < num_atoms; i1++)
    1585                 :             :     {
    1586   [ +  +  +  - ]:         597 :         if (at[i1].valence != 3 || !at[i1].stereo_bond_neighbor[0])
    1587                 :             :         {
    1588                 :         597 :             continue;
    1589                 :             :         }
    1590   [ #  #  #  # ]:           0 :         for (n1 = 0; n1 < MAX_NUM_STEREO_BONDS && ( s2 = at[i1].stereo_bond_neighbor[n1] ); n1++)
    1591                 :             :         {
    1592   [ #  #  #  #  :           0 :             if (!PARITY_CALCULATE( at[i1].stereo_bond_parity[n1] ) && PARITY_WELL_DEF( at[i1].stereo_bond_parity[n1] ))
                   #  # ]
    1593                 :             :             {
    1594                 :           0 :                 continue;
    1595                 :             :             }
    1596                 :           0 :             opposite_atom = (AT_RANK) ( s2 - 1 );
    1597                 :             :             /* s2 = at[i1].neighbor[m=(int)at[i1].stereo_bond_ord[n1]]; */
    1598                 :           0 :             m = (int) at[i1].stereo_bond_ord[n1];
    1599         [ #  # ]:           0 :             for (j = 0, n = 0; j < at[i1].valence; j++)
    1600                 :             :             {
    1601                 :             :                 /* if ( at[i1].neighbor[j] != s2 ) */
    1602         [ #  # ]:           0 :                 if (j != m)
    1603                 :             :                 {
    1604                 :           0 :                     neigh[n++] = at[i1].neighbor[j];
    1605                 :             :                 }
    1606                 :             :             }
    1607         [ #  # ]:           0 :             if (n > 2)
    1608                 :             :             {
    1609                 :           0 :                 ret = CT_STEREOBOND_ERROR;  /*   <BRKPT> */
    1610                 :           0 :                 goto exit_function;
    1611                 :             :             }
    1612   [ #  #  #  # ]:           0 :             if (n != 2 || nRank[(int) neigh[0]] != nRank[(int) neigh[1]])
    1613                 :             :             {
    1614                 :           0 :                 continue; /*  may happen if another half-bond has not a defined parity */
    1615                 :             :             }
    1616         [ #  # ]:           0 :             if (at[i1].nRingSystem == at[(int) neigh[0]].nRingSystem)
    1617                 :             :             {
    1618                 :           0 :                 continue;  /*  no more ring system membership check is necessary because     */
    1619                 :             :             }              /*  the two neighbors are to be constitutionally equivalent atoms */
    1620   [ #  #  #  # ]:           0 :             if (!nVisited && !( nVisited = (AT_RANK*) inchi_malloc( sizeof( nVisited[0] )*num_atoms ) ))
    1621                 :             :             {
    1622                 :           0 :                 ret = CT_OUT_OF_RAM;  /*   <BRKPT> */
    1623                 :           0 :                 goto exit_function;
    1624                 :             :             }
    1625                 :           0 :             memset( nVisited, 0, sizeof( nVisited[0] )*num_atoms ); /* djb-rwth: memset_s C11/Annex K variant? */
    1626                 :           0 :             nVisited[i1] = 1;
    1627         [ #  # ]:           0 :             if (PathsHaveIdenticalKnownParities( at, (AT_RANK) i1, neigh[0], (AT_RANK) i1, neigh[1], nVisited, nVisited, nRank, nCanonRank, 1 ))
    1628                 :             :             {
    1629         [ #  # ]:           0 :                 if (!RemoveOneStereoBond( at, i1, /* atom number*/ n1 /* stereo bond number*/ ))
    1630                 :             :                 {
    1631                 :           0 :                     ret = CT_STEREOBOND_ERROR;  /*   <BRKPT> */
    1632                 :           0 :                     goto exit_function;
    1633                 :             :                 }
    1634                 :           0 :                 n1--; /*  cycle counter may temporarily become negative */
    1635                 :             :                 /*  Remove from pCS */
    1636                 :           0 :                 nAtomRank1 = inchi_max( nCanonRank[i1], nCanonRank[opposite_atom] );
    1637                 :           0 :                 nAtomRank2 = inchi_min( nCanonRank[i1], nCanonRank[opposite_atom] );
    1638         [ #  # ]:           0 :                 for (n = 0, m = pCS->nLenLinearCTStereoDble - 1; n <= m; n++)
    1639                 :             :                 {
    1640         [ #  # ]:           0 :                     if (pCS->LinearCTStereoDble[n].at_num1 == nAtomRank1 &&
    1641         [ #  # ]:           0 :                          pCS->LinearCTStereoDble[n].at_num2 == nAtomRank2)
    1642                 :             :                     {
    1643         [ #  # ]:           0 :                         if (n < m)
    1644                 :             :                         { /*  remove pCS->LinearCTStereoDble[n] */
    1645                 :           0 :                             memmove( pCS->LinearCTStereoDble + n, pCS->LinearCTStereoDble + n + 1, ( (long long)m - (long long)n ) * sizeof( pCS->LinearCTStereoDble[0] ) ); /* djb-rwth: cast operators added */
    1646                 :             :                         }
    1647                 :           0 :                         pCS->nLenLinearCTStereoDble--;
    1648                 :             : #if ( bRELEASE_VERSION == 0 )
    1649                 :             :                         pCS->bExtract |= EXTR_KNOWN_USED_TO_REMOVE_PARITY;
    1650                 :             : #endif
    1651                 :           0 :                         m = -1;   /*  set flag "found" */
    1652                 :           0 :                         break;
    1653                 :             :                     }
    1654                 :             :                 }
    1655         [ #  # ]:           0 :                 if (m >= 0)
    1656                 :             :                 {
    1657                 :           0 :                     ret = CT_STEREOCOUNT_ERR;  /*  bond not found  <BRKPT> */
    1658                 :           0 :                     goto exit_function;
    1659                 :             :                 }
    1660                 :           0 :                 ret++;  /*  number of removed known in advance non-stereo bonds */
    1661                 :             :             }
    1662                 :             :         }
    1663                 :             :     }
    1664                 :             : 
    1665                 :          59 : exit_function:
    1666         [ -  + ]:          59 :     if (nVisited)
    1667                 :             :     {
    1668         [ #  # ]:           0 :         inchi_free( nVisited );
    1669                 :             :     }
    1670                 :             : 
    1671                 :          59 :     return ret;
    1672                 :             : }
    1673                 :             : #endif /* } REMOVE_KNOWN_NONSTEREO */
    1674                 :             : 
    1675                 :             : 
    1676                 :             : /****************************************************************************
    1677                 :             :  Find stereo center parities known in advance
    1678                 :             : ****************************************************************************/
    1679                 :          58 : int SetKnownStereoCenterParities( CANON_GLOBALS *pCG,
    1680                 :             :                                   sp_ATOM       *at,
    1681                 :             :                                   int           num_atoms,
    1682                 :             :                                   const AT_RANK *nCanonRank,
    1683                 :             :                                   const AT_RANK *nRank,
    1684                 :             :                                   const AT_RANK *nAtomNumber )
    1685                 :             : {
    1686                 :             :     int i, j, n, m, j1, k, num_neigh, iMax, trans_i, trans_k, prev_trans, num_set;
    1687                 :             :     AT_RANK nAtomRank;
    1688                 :             :     AT_RANK nNeighRank[MAX_NUM_STEREO_ATOM_NEIGH];
    1689                 :             :     AT_RANK nNeighCanonRank[MAX_NUM_STEREO_ATOM_NEIGH];
    1690                 :             : 
    1691         [ +  + ]:         642 :     for (i = 0, num_set = 0; i < num_atoms; i++)
    1692                 :             :     {
    1693   [ +  +  -  + ]:         584 :         if (!at[i].parity || at[i].stereo_bond_neighbor[0])
    1694                 :             :         {
    1695                 :         396 :             continue;
    1696                 :             :         }
    1697         [ +  + ]:         188 :         if (at[i].stereo_atom_parity != AB_PARITY_CALC ||
    1698   [ +  -  -  + ]:         167 :              !PARITY_WELL_DEF( at[i].parity ))
    1699                 :             :         {
    1700                 :          21 :             continue;
    1701                 :             :         }
    1702                 :         167 :         num_neigh = at[i].valence;
    1703         [ +  + ]:         668 :         for (j = 0; j < num_neigh; j++)
    1704                 :             :         {
    1705                 :         501 :             nNeighRank[j] = nRank[(int) at[i].neighbor[j]];
    1706                 :             :         }
    1707                 :         167 :         nAtomRank = nRank[i];
    1708         [ -  + ]:         167 :         if (num_neigh == 1)
    1709                 :             :         {
    1710                 :             :             /* other neighbors must be implicit H */
    1711                 :           0 :             at[i].stereo_atom_parity = at[i].parity;
    1712                 :           0 :             trans_i = 0;
    1713                 :             :         }
    1714                 :             :         else
    1715                 :             :         {
    1716                 :             :             /* sort constitutional equivalence ranks of the neighbors */
    1717                 :         167 :             trans_i = insertions_sort( pCG, nNeighRank, num_neigh, sizeof( nNeighRank[0] ), comp_AT_RANK );
    1718         [ +  + ]:         501 :             for (j = 1; j < num_neigh; j++)
    1719                 :             :             {
    1720         [ -  + ]:         334 :                 if (nNeighRank[j - 1] == nNeighRank[j])
    1721                 :             :                 {
    1722                 :           0 :                     break; /* at[i] has consitutionally identical neighbors */
    1723                 :             :                 }
    1724                 :             :             }
    1725         [ -  + ]:         167 :             if (j < num_neigh)
    1726                 :             :             {
    1727                 :             :                 /*  at least 2 neighbors are const. identical; parity cannot be calculated at this time */
    1728                 :           0 :                 continue; /*  try next stereo atom */
    1729                 :             :             }
    1730                 :             :         }
    1731                 :         167 :         prev_trans = -1;
    1732                 :         167 :         trans_k = 0;
    1733                 :             :         /*  find neighbors of constitutionally equivalent stereo centers */
    1734                 :             :         /*  and at[i] parities in case those centers are mapped on at[i] */
    1735                 :         167 :         for (iMax = (int) nAtomRank - 1, j1 = 0;
    1736   [ +  -  +  + ]:         336 :                 j1 <= iMax && nAtomRank == nRank[k = (int) nAtomNumber[iMax - j1]];
    1737                 :         169 :                     j1++)
    1738                 :             :         {
    1739                 :             :             /*  at[k] is constitutionally equivalent to at[i] */
    1740         [ -  + ]:         169 :             if ((int) at[k].valence != num_neigh)
    1741                 :             :             {
    1742                 :           0 :                 return CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
    1743                 :             :             }
    1744                 :             :             /* -- commented out to accept  non-stereogenic atoms since     --
    1745                 :             :                -- they may participate in mapping stereocenters 12-16-2003 --
    1746                 :             :             if ( !PARITY_VAL(at[k].parity) ) {
    1747                 :             :                 continue; // not a stereogenic atom
    1748                 :             :             }
    1749                 :             :             */
    1750         [ +  + ]:         676 :             for (j = 0, m = 0; m < num_neigh; m++)
    1751                 :             :             {
    1752         [ +  - ]:        1014 :                 for (n = 0; n < num_neigh; n++)
    1753                 :             :                 {
    1754         [ +  + ]:        1014 :                     if (nRank[(int) at[k].neighbor[n]] == nNeighRank[m])
    1755                 :             :                     {
    1756                 :             :                         /* save canonical numbers (ranks) of the neighbors in
    1757                 :             :                          * order of increasing constit. equivalence ranks */
    1758                 :         507 :                         nNeighCanonRank[m] = nCanonRank[(int) at[k].neighbor[n]];
    1759                 :         507 :                         j++;
    1760                 :         507 :                         break;
    1761                 :             :                     }
    1762                 :             :                 }
    1763                 :             :             }
    1764         [ -  + ]:         169 :             if (j != num_neigh)
    1765                 :             :             {
    1766                 :           0 :                 return CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
    1767                 :             :             }
    1768                 :         169 :             trans_k = insertions_sort( pCG, nNeighCanonRank, num_neigh, sizeof( nNeighCanonRank[0] ), comp_AT_RANK );
    1769                 :         169 :             trans_k %= 2;
    1770         [ +  + ]:         169 :             if (prev_trans < 0)
    1771                 :             :             {
    1772                 :         167 :                 prev_trans = trans_k;
    1773                 :             :             }
    1774         [ -  + ]:           2 :             else if (trans_k != prev_trans)
    1775                 :             :             {
    1776                 :             :                 /*  different mappings may produce different parities. Cannot find the parity at this time */
    1777                 :             :                 /*  this may happen when a set of constit. equivalent atoms has non-contiguous canonical numbers */
    1778                 :           0 :                 break;
    1779                 :             :             }
    1780                 :             :         }
    1781         [ +  - ]:         167 :         if (trans_k == prev_trans)
    1782                 :             :         {
    1783                 :         167 :             at[i].stereo_atom_parity = 2 - ( at[i].parity + trans_i + prev_trans ) % 2;
    1784                 :         167 :             num_set++;
    1785                 :             :         }
    1786                 :             :     }
    1787                 :             : 
    1788                 :          58 :     return num_set;
    1789                 :             : }
    1790                 :             : 
    1791                 :             : 
    1792                 :             : #if ( REMOVE_KNOWN_NONSTEREO == 1 ) /* { */
    1793                 :             : 
    1794                 :             : 
    1795                 :             : /****************************************************************************
    1796                 :             :  DFS along paths starting from the stereocenter through pairs of cut-edges
    1797                 :             : ****************************************************************************/
    1798                 :          59 : int RemoveKnownNonStereoCenterParities( CANON_GLOBALS *pCG,
    1799                 :             :                                         sp_ATOM       *at,
    1800                 :             :                                         int           num_atoms,
    1801                 :             :                                         const AT_RANK *nCanonRank,
    1802                 :             :                                         const AT_RANK *nRank,
    1803                 :             :                                         CANON_STAT    *pCS )
    1804                 :             : {
    1805                 :          59 :     int i, j, n, m, k, num_neigh, ret = 0;
    1806                 :             :     /*AT_RANK nAtomRank;*/
    1807                 :             :     AT_RANK nNeighRank[MAX_NUM_STEREO_ATOM_NEIGH], nNeighOrd[MAX_NUM_STEREO_ATOM_NEIGH];
    1808                 :          59 :     AT_RANK *nVisited = NULL;
    1809                 :             : 
    1810         [ +  + ]:         656 :     for (i = 0; i < num_atoms; i++)
    1811                 :             :     {
    1812   [ +  +  -  + ]:         597 :         if (!at[i].parity || at[i].stereo_bond_neighbor[0])
    1813                 :             :         {
    1814                 :         408 :             continue;
    1815                 :             :         }
    1816   [ +  -  +  -  :         189 :         if (!PARITY_CALCULATE( at[i].stereo_atom_parity ) && PARITY_WELL_DEF( at[i].stereo_atom_parity ))
                   +  + ]
    1817                 :             :         {
    1818                 :         167 :             continue;
    1819                 :             :         }
    1820                 :          22 :         num_neigh = at[i].valence;
    1821         [ +  + ]:          88 :         for (j = 0; j < num_neigh; j++)
    1822                 :             :         {
    1823                 :          66 :             nNeighRank[j] = nRank[(int) at[i].neighbor[j]];
    1824                 :          66 :             nNeighOrd[j] = j;
    1825                 :             :         }
    1826                 :             :         /*nAtomRank = nRank[i];*/
    1827         [ -  + ]:          22 :         if (num_neigh == 1)
    1828                 :             :         {
    1829                 :           0 :             continue;
    1830                 :             :         }
    1831                 :          22 :         pCG->m_pn_RankForSort = nNeighRank;
    1832                 :          22 :         insertions_sort( pCG, nNeighOrd, num_neigh, sizeof( nNeighRank[0] ), CompRanksOrd );
    1833   [ +  +  +  + ]:          65 :         for (j = k = 1; k && j < num_neigh; j++)
    1834                 :             :         {
    1835         [ +  + ]:          43 :             if (at[i].nRingSystem != at[(int) at[i].neighbor[(int) nNeighOrd[j]]].nRingSystem &&
    1836                 :             :                  /*  no more ring system membership check is necessary because */
    1837                 :             :                  /*  the two neighbors are to be constitutionally equivalent atoms: */
    1838         [ +  + ]:          35 :                 nNeighRank[nNeighOrd[j - 1]] == nNeighRank[nNeighOrd[j]])
    1839                 :             :             {
    1840                 :           1 :                 k = j;
    1841                 :             :                 do
    1842                 :             :                 {
    1843   [ +  -  -  + ]:           1 :                     if (!nVisited && !( nVisited = (AT_RANK*) inchi_malloc( sizeof( nVisited[0] )*num_atoms ) ))
    1844                 :             :                     {
    1845                 :           0 :                         ret = CT_OUT_OF_RAM;  /*   <BRKPT> */
    1846                 :           0 :                         goto exit_function;
    1847                 :             :                     }
    1848                 :           1 :                     memset( nVisited, 0, sizeof( nVisited[0] )*num_atoms ); /* djb-rwth: memset_s C11/Annex K variant? */
    1849                 :           1 :                     nVisited[i] = 1;
    1850         [ +  - ]:           1 :                     if (PathsHaveIdenticalKnownParities( at, (AT_RANK) i, at[i].neighbor[(int) nNeighOrd[j - 1]],
    1851                 :           1 :                         (AT_RANK) i, at[i].neighbor[(int) nNeighOrd[k]],
    1852                 :             :                         nVisited, nVisited, nRank, nCanonRank, 1 ))
    1853                 :             :                     {
    1854                 :           1 :                         at[i].parity = 0; /*  remove parity */
    1855                 :           1 :                         at[i].stereo_atom_parity = 0;
    1856                 :           1 :                         at[i].final_parity = 0;
    1857                 :             :                         /* at[i].bHasStereoOrEquToStereo = 0; */
    1858         [ +  - ]:           2 :                         for (n = 0, m = pCS->nLenLinearCTStereoCarb - 1; n <= m; n++)
    1859                 :             :                         {
    1860         [ +  + ]:           2 :                             if (pCS->LinearCTStereoCarb[n].at_num == nCanonRank[i])
    1861                 :             :                             {
    1862         [ -  + ]:           1 :                                 if (n < m)
    1863                 :             :                                 {    /*  remove pCS->LinearCTStereoCarb[n] */
    1864                 :           0 :                                     memmove( pCS->LinearCTStereoCarb + n, pCS->LinearCTStereoCarb + n + 1, ( (long long)m - (long long)n ) * sizeof( pCS->LinearCTStereoCarb[0] ) ); /* djb-rwth: cast operators added */
    1865                 :             :                                 }
    1866                 :           1 :                                 pCS->nLenLinearCTStereoCarb--;
    1867                 :           1 :                                 k = 0;
    1868                 :             : 
    1869                 :             : #if ( bRELEASE_VERSION == 0 )
    1870                 :             :                                 pCS->bExtract |= EXTR_KNOWN_USED_TO_REMOVE_PARITY;
    1871                 :             : #endif
    1872                 :             : 
    1873                 :           1 :                                 break;
    1874                 :             :                             }
    1875                 :             :                         }
    1876         [ -  + ]:           1 :                         if (k)
    1877                 :             :                         {
    1878                 :           0 :                             ret = CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
    1879                 :           0 :                             goto exit_function;
    1880                 :             :                         }
    1881                 :           1 :                         ret++;
    1882                 :           1 :                         break;
    1883                 :             :                     }
    1884                 :             :                 }
    1885   [ #  #  #  # ]:           0 :                 while (++k < num_neigh && nNeighRank[nNeighOrd[j - 1]] == nNeighRank[nNeighOrd[k]]);
    1886                 :             :             }
    1887                 :             :         }
    1888                 :             :     }
    1889                 :             : 
    1890                 :          59 : exit_function:
    1891         [ +  + ]:          59 :     if (nVisited)
    1892                 :             :     {
    1893         [ +  - ]:           1 :         inchi_free( nVisited );
    1894                 :             :     }
    1895                 :             : 
    1896                 :          59 :     return ret;
    1897                 :             : }
    1898                 :             : 
    1899                 :             : 
    1900                 :             : 
    1901                 :             : #endif /* } REMOVE_KNOWN_NONSTEREO */
    1902                 :             : 
    1903                 :             : 
    1904                 :             : /****************************************************************************
    1905                 :             :  Find stereo center parities known in advance
    1906                 :             : ****************************************************************************/
    1907                 :          58 : int MarkKnownEqualStereoCenterParities( sp_ATOM       *at,
    1908                 :             :                                         int           num_atoms,
    1909                 :             :                                         const AT_RANK *nRank,
    1910                 :             :                                         const AT_RANK *nAtomNumber )
    1911                 :             : {
    1912                 :             :     int i, j1, k, num_centers, iMax, bDifferentParities;
    1913                 :             :     AT_RANK nAtomRank;
    1914                 :             :     int  parity, parity_k;
    1915                 :             : 
    1916                 :          58 :     num_centers = 0;
    1917         [ +  + ]:         642 :     for (i = 0; i < num_atoms; i++)
    1918                 :             :     {
    1919   [ +  +  -  + ]:         584 :         if (!at[i].parity || at[i].stereo_bond_neighbor[0])
    1920                 :             :         {
    1921                 :         396 :             continue;
    1922                 :             :         }
    1923         [ +  + ]:         188 :         if (at[i].bHasStereoOrEquToStereo)
    1924                 :             :         {
    1925                 :           1 :             continue; /* already marked */
    1926                 :             :         }
    1927         [ -  + ]:         187 :         if ( /*!PARITY_KNOWN(at[i].stereo_atom_parity) ||*/ ( at[i].stereo_atom_parity & KNOWN_PARITIES_EQL ))
    1928                 :             :         {
    1929                 :           0 :             continue;
    1930                 :             :         }
    1931                 :         187 :         parity = PARITY_VAL( at[i].stereo_atom_parity );
    1932         [ -  + ]:         187 :         if (parity == AB_PARITY_NONE)
    1933                 :             :         {
    1934                 :           0 :             continue;
    1935                 :             :         }
    1936                 :         187 :         nAtomRank = nRank[i];
    1937                 :         187 :         bDifferentParities = -1;
    1938                 :             :         /*  find constitutionally equivalent stereo centers and compare their known at this time parities */
    1939   [ +  -  +  + ]:         375 :         for (iMax = (int) nAtomRank - 1, j1 = 0; j1 <= iMax && nAtomRank == nRank[k = (int) nAtomNumber[iMax - j1]]; j1++)
    1940                 :             :         {
    1941                 :             :             /*  at[k] is constitutionally equivalent to at[i] */
    1942                 :         188 :             parity_k = PARITY_VAL( at[k].stereo_atom_parity );
    1943         [ -  + ]:         188 :             if (parity_k != parity)
    1944                 :             :             {
    1945                 :           0 :                 bDifferentParities = 1;
    1946                 :             :             }
    1947   [ +  -  +  + ]:         188 :             else if (parity_k == parity && bDifferentParities < 0)
    1948                 :             :             {
    1949                 :         187 :                 bDifferentParities = 0;
    1950                 :             :             }
    1951         [ -  + ]:         188 :             if (!parity_k)
    1952                 :             :             {
    1953                 :           0 :                 at[k].bHasStereoOrEquToStereo = 2;
    1954                 :             :             }
    1955         [ +  - ]:         188 :             else if (!at[k].bHasStereoOrEquToStereo)
    1956                 :             :             {
    1957                 :         188 :                 at[k].bHasStereoOrEquToStereo = 1;
    1958                 :             :             }
    1959                 :             :         }
    1960   [ +  -  +  -  :         187 :         if (0 == bDifferentParities && PARITY_KNOWN( parity ))
                   +  - ]
    1961                 :             :         {
    1962   [ +  -  +  + ]:         375 :             for (iMax = (int) nAtomRank - 1, j1 = 0; j1 <= iMax && nAtomRank == nRank[k = (int) nAtomNumber[iMax - j1]]; j1++)
    1963                 :             :             {
    1964                 :             :                 /*  at[k] is constitutionally equivalent to at[i] */
    1965                 :         188 :                 at[k].stereo_atom_parity |= KNOWN_PARITIES_EQL;
    1966                 :         188 :                 num_centers++;
    1967                 :             :             }
    1968                 :             :         }
    1969                 :             :     }
    1970                 :             : 
    1971                 :          58 :     return num_centers;
    1972                 :             : }
    1973                 :             : 
    1974                 :             : 
    1975                 :             : /*****************************************************************************/
    1976                 :             : /* invert known parities in at[] and in pCS->LinearCTStereoDble              */
    1977                 :             : /*                                      pCS->LinearCTStereoCarb              */
    1978                 :             : /* nCanonRank[] contains canonical ranks used to fill pCS->LinearCTStereo... */
    1979                 :             : /* nAtomNumberCanon[] will be filled with atom numbers in canonical order    */
    1980                 :             : /*****************************************************************************/
    1981                 :         109 : int InvertStereo( sp_ATOM    *at,
    1982                 :             :                   int        num_at_tg,
    1983                 :             :                   AT_RANK    *nCanonRank,
    1984                 :             :                   AT_RANK    *nAtomNumberCanon,
    1985                 :             :                   CANON_STAT *pCS,
    1986                 :             :                   int        bInvertLinearCTStereo )
    1987                 :             : {
    1988                 :             :     int i, j, j1, j2, num_changes, parity, cumulene_len;
    1989                 :             : 
    1990                 :         109 :     num_changes = 0;
    1991         [ +  + ]:        1221 :     for (i = 0; i < num_at_tg; i++)
    1992                 :             :     {
    1993                 :        1112 :         nAtomNumberCanon[(int) nCanonRank[i] - 1] = i;
    1994                 :             :     }
    1995         [ +  + ]:         476 :     for (i = 0; i < pCS->nLenLinearCTStereoCarb; i++)
    1996                 :             :     {
    1997                 :         367 :         parity = pCS->LinearCTStereoCarb[i].parity;
    1998   [ +  -  +  + ]:         367 :         if (ATOM_PARITY_WELL_DEF( parity ))
    1999                 :             :         {
    2000                 :         334 :             j = nAtomNumberCanon[(int) pCS->LinearCTStereoCarb[i].at_num - 1];
    2001   [ +  -  +  - ]:         334 :             if (PARITY_WELL_DEF( at[j].parity ))
    2002                 :             :             {
    2003                 :         334 :                 at[j].parity ^= AB_INV_PARITY_BITS;
    2004                 :             :             }
    2005                 :             :             else
    2006                 :             :             {
    2007                 :           0 :                 goto exit_error; /* inconsistency */
    2008                 :             :             }
    2009         [ +  + ]:         334 :             if (bInvertLinearCTStereo)
    2010                 :             :             {
    2011                 :             : #ifdef FIX_STEREOCOUNT_ERR
    2012                 :         167 :                 pCS->LinearCTStereoCarb[i].parity = AB_PARITY_EVEN; /* deliberately worse */
    2013                 :             : #else
    2014                 :             :                 pCS->LinearCTStereoCarb[i].parity ^= AB_INV_PARITY_BITS;
    2015                 :             : #endif
    2016                 :             :             }
    2017                 :         334 :             num_changes++;
    2018   [ +  -  +  - ]:         334 :             if (PARITY_WELL_DEF( at[j].stereo_atom_parity ))
    2019                 :             :             {
    2020                 :         334 :                 at[j].stereo_atom_parity ^= AB_INV_PARITY_BITS;
    2021                 :             :             }
    2022   [ -  +  -  - ]:         334 :             if (PARITY_WELL_DEF( at[j].final_parity ))
    2023                 :             :             {
    2024                 :           0 :                 at[j].final_parity ^= AB_INV_PARITY_BITS;
    2025                 :             :             }
    2026                 :             :         }
    2027                 :             :     }
    2028         [ -  + ]:         109 :     for (i = 0; i < pCS->nLenLinearCTStereoDble; i++)
    2029                 :             :     {
    2030                 :           0 :         parity = pCS->LinearCTStereoDble[i].parity;
    2031   [ #  #  #  # ]:           0 :         if (ATOM_PARITY_WELL_DEF( parity ))
    2032                 :             :         {
    2033                 :           0 :             j1 = nAtomNumberCanon[(int) pCS->LinearCTStereoDble[i].at_num1 - 1];
    2034                 :           0 :             cumulene_len = BOND_CHAIN_LEN( at[j1].stereo_bond_parity[0] );
    2035         [ #  # ]:           0 :             if (cumulene_len % 2)
    2036                 :             :             {
    2037                 :             :                 /* invert only in case of allene */
    2038                 :           0 :                 j2 = nAtomNumberCanon[(int) pCS->LinearCTStereoDble[i].at_num2 - 1];
    2039                 :             :                 /* checks for debug only */
    2040                 :             :                 if (1 < MAX_NUM_STEREO_BONDS)
    2041                 :             :                 {
    2042         [ #  # ]:           0 :                     if (at[j1].stereo_bond_neighbor[1] ||
    2043         [ #  # ]:           0 :                          at[j2].stereo_bond_neighbor[1])
    2044                 :             :                     {
    2045                 :           0 :                         goto exit_error; /* inconsitency: atom has more than one cumulene bond */
    2046                 :             :                     }
    2047                 :             :                 }
    2048         [ #  # ]:           0 :                 if (cumulene_len != BOND_CHAIN_LEN( at[j2].stereo_bond_parity[0] ) ||
    2049         [ #  # ]:           0 :                      j1 + 1 != at[j2].stereo_bond_neighbor[0] ||
    2050         [ #  # ]:           0 :                      j2 + 1 != at[j1].stereo_bond_neighbor[0])
    2051                 :             :                 {
    2052                 :           0 :                     goto exit_error; /* inconsitency: atoms should refer to each other */
    2053                 :             :                 }
    2054                 :             :                 /* invert parities */
    2055   [ #  #  #  #  :           0 :                 if (PARITY_WELL_DEF( at[j1].parity ) && PARITY_WELL_DEF( at[j2].parity ))
             #  #  #  # ]
    2056                 :             :                 {
    2057                 :           0 :                     j = inchi_min( j1, j2 );
    2058                 :           0 :                     at[j].parity ^= AB_INV_PARITY_BITS; /* for reversability always invert only atom with the smaller number */
    2059                 :             :                 }
    2060                 :             :                 else
    2061                 :             :                 {
    2062                 :           0 :                     goto exit_error; /* inconsistency */
    2063                 :             :                 }
    2064         [ #  # ]:           0 :                 if (bInvertLinearCTStereo)
    2065                 :             :                 {
    2066                 :           0 :                     pCS->LinearCTStereoDble[i].parity ^= AB_INV_PARITY_BITS;
    2067                 :             :                 }
    2068                 :           0 :                 num_changes++;
    2069   [ #  #  #  # ]:           0 :                 if (PARITY_WELL_DEF( at[j1].stereo_bond_parity[0] ))
    2070                 :             :                 {
    2071                 :           0 :                     at[j1].stereo_bond_parity[0] ^= AB_INV_PARITY_BITS;
    2072                 :             :                 }
    2073   [ #  #  #  # ]:           0 :                 if (PARITY_WELL_DEF( at[j2].stereo_bond_parity[0] ))
    2074                 :             :                 {
    2075                 :           0 :                     at[j2].stereo_bond_parity[0] ^= AB_INV_PARITY_BITS;
    2076                 :             :                 }
    2077                 :             :             }
    2078                 :             :         }
    2079                 :             :     }
    2080                 :             : 
    2081                 :         109 :     return num_changes;
    2082                 :             : 
    2083                 :           0 : exit_error:
    2084                 :           0 :     return CT_STEREOCOUNT_ERR;
    2085                 :             : }
    2086                 :             : 
    2087                 :             : 
    2088                 :             : /********************************************************************************/
    2089                 :             : /*  Make sure atoms stereo descriptors fit molecular symmetry and remove        */
    2090                 :             : /*  parity from obviously non-stereo atoms and bonds                            */
    2091                 :             : /********************************************************************************/
    2092                 :          58 : int FillOutStereoParities( sp_ATOM       *at,
    2093                 :             :                            int           num_atoms,
    2094                 :             :                            const AT_RANK *nCanonRank,
    2095                 :             :                            const AT_RANK *nAtomNumberCanon,
    2096                 :             :                            const AT_RANK *nRank,
    2097                 :             :                            const AT_RANK *nAtomNumber,
    2098                 :             :                            CANON_STAT    *pCS,
    2099                 :             :                            CANON_GLOBALS *pCG,
    2100                 :             :                            int           bIsotopic )
    2101                 :             : {
    2102                 :             :     int ret;
    2103                 :             :     /*  unmark atoms with 2 or more constitutionally equivalent neighbors */
    2104                 :             :     /*  such that there is no path through them to an atom with parity */
    2105                 :          58 :     ret = UnmarkNonStereo( pCG, at, num_atoms, nRank, nAtomNumber, bIsotopic );
    2106         [ -  + ]:          58 :     if (ret < 0)
    2107                 :           0 :         return ret;  /*  program error? */ /*   <BRKPT> */
    2108                 :          58 :     ret = FillAllStereoDescriptors( pCG, at, num_atoms, nCanonRank, nAtomNumberCanon, pCS ); /*  ret<0: error */
    2109         [ +  - ]:          58 :     if (!ret)
    2110                 :             :     {
    2111                 :          58 :         ret = pCS->nLenLinearCTStereoCarb + pCS->nLenLinearCTStereoDble;
    2112                 :             :     }
    2113         [ -  + ]:          58 :     if (ret < 0)
    2114                 :             :     {
    2115                 :           0 :         return ret; /*  program error? */ /*   <BRKPT> */
    2116                 :             :     }
    2117                 :             : 
    2118         [ +  - ]:          58 :     if (ret >= 0)
    2119                 :             :     {
    2120                 :             :         int ret2;
    2121                 :          58 :         ret2 = SetKnownStereoCenterParities( pCG, at, num_atoms, nCanonRank, nRank, nAtomNumber );
    2122         [ +  - ]:          58 :         if (ret2 >= 0)
    2123                 :             :         {
    2124                 :          58 :             ret2 = MarkKnownEqualStereoCenterParities( at, num_atoms, nRank, nAtomNumber );
    2125                 :             :         }
    2126         [ +  - ]:          58 :         if (ret2 >= 0)
    2127                 :             :         {
    2128                 :          58 :             ret2 = SetKnownStereoBondParities( pCG, at, num_atoms, nCanonRank, nRank, nAtomNumber );
    2129         [ +  - ]:          58 :             if (ret2 >= 0)
    2130                 :             :             {
    2131                 :          58 :                 ret2 = MarkKnownEqualStereoBondParities( at, num_atoms, nRank, nAtomNumber );
    2132                 :             :             }
    2133                 :             :         }
    2134                 :             : #if ( REMOVE_KNOWN_NONSTEREO == 1 ) /* { */
    2135         [ +  - ]:          58 :         if (ret2 >= 0)
    2136                 :             :         {
    2137                 :             :             int ret3;
    2138                 :             :             do
    2139                 :             :             {
    2140                 :          59 :                 ret2 = RemoveKnownNonStereoCenterParities( pCG, at, num_atoms, nCanonRank, nRank, pCS );
    2141         [ +  - ]:          59 :                 if (ret2 >= 0)
    2142                 :             :                 {
    2143                 :          59 :                     ret3 = RemoveKnownNonStereoBondParities( at, num_atoms, nCanonRank, nRank, pCS );
    2144         [ +  - ]:          59 :                     ret2 = ret3 >= 0 ? ret2 + ret3 : ret3;
    2145                 :             :                 }
    2146                 :             :             }
    2147         [ +  + ]:          59 :             while (ret2 > 0);
    2148                 :             :         }
    2149   [ +  -  -  + ]:          58 :         if (RETURNED_ERROR( ret2 ))
    2150                 :             :         {
    2151                 :           0 :             ret = ret2;
    2152                 :             :         }
    2153                 :             : #endif /* } REMOVE_KNOWN_NONSTEREO */
    2154                 :             :     }
    2155                 :             : 
    2156                 :          58 :     return ret; /*  non-zero means error */
    2157                 :             : }
    2158                 :             : 
    2159                 :             : 
    2160                 :             : 
    2161                 :             : /****************************************************************************/
    2162                 :           0 : int GetStereoNeighborPos( sp_ATOM *at,
    2163                 :             :                           int     iAt1,
    2164                 :             :                           int     iAt2 )
    2165                 :             : {
    2166                 :             :     int k1;
    2167                 :           0 :     AT_RANK sNeigh = (AT_RANK) ( iAt2 + 1 );
    2168                 :             :     AT_RANK s;
    2169   [ #  #  #  # ]:           0 :     for (k1 = 0; k1 < MAX_NUM_STEREO_BONDS && ( s = at[iAt1].stereo_bond_neighbor[k1] ); k1++)
    2170                 :             :     {
    2171         [ #  # ]:           0 :         if (s == sNeigh)
    2172                 :             :         {
    2173                 :           0 :             return k1;
    2174                 :             :         }
    2175                 :             :     }
    2176                 :             : 
    2177                 :           0 :     return -1; /*  neighbor not found */
    2178                 :             : }
    2179                 :             : 
    2180                 :             : 
    2181                 :             : /****************************************************************************
    2182                 :             :  Extracted from FillSingleStereoDescriptors(...)
    2183                 :             : ****************************************************************************/
    2184                 :           0 : int GetStereoBondParity( sp_ATOM *at,
    2185                 :             :                          int     i,
    2186                 :             :                          int     n,
    2187                 :             :                          AT_RANK *nRank )
    2188                 :             : {
    2189                 :             :     int k1, k2, s, parity;
    2190                 :             : 
    2191         [ #  # ]:           0 :     if (at[i].stereo_bond_neighbor[0])
    2192                 :             :     {
    2193   [ #  #  #  # ]:           0 :         for (k1 = 0; k1 < MAX_NUM_STEREO_BONDS && ( s = (int) at[i].stereo_bond_neighbor[k1] ); k1++)
    2194                 :             :         {
    2195         [ #  # ]:           0 :             if (--s == n)
    2196                 :             :             {
    2197                 :           0 :                 goto neigh1_found;
    2198                 :             :             }
    2199                 :             :         }
    2200                 :           0 :         return -1; /*  error: not a stereo neighbor */
    2201                 :           0 :     neigh1_found:
    2202   [ #  #  #  # ]:           0 :         if (PARITY_KNOWN( at[i].stereo_bond_parity[k1] ))
    2203                 :             :         {
    2204                 :           0 :             return PARITY_VAL( at[i].stereo_bond_parity[k1] );
    2205                 :             :         }
    2206   [ #  #  #  # ]:           0 :         for (k2 = 0; k2 < MAX_NUM_STEREO_BONDS && ( s = (int) at[n].stereo_bond_neighbor[k2] ); k2++)
    2207                 :             :         {
    2208         [ #  # ]:           0 :             if (--s == i)
    2209                 :             :             {
    2210                 :           0 :                 goto neigh2_found;
    2211                 :             :             }
    2212                 :             :         }
    2213                 :           0 :         return -1; /*  error: not a stereo neighbor */
    2214                 :           0 :     neigh2_found:;
    2215                 :             :     }
    2216                 :             :     else
    2217                 :             :     {
    2218                 :           0 :         return -1; /*  error: not a stereo bond */
    2219                 :             :     }
    2220                 :             : 
    2221   [ #  #  #  # ]:           0 :     if (ATOM_PARITY_WELL_DEF( at[i].parity ) &&
    2222   [ #  #  #  # ]:           0 :          ATOM_PARITY_WELL_DEF( at[n].parity ) &&
    2223         [ #  # ]:           0 :          MIN_DOT_PROD <= abs( at[i].stereo_bond_z_prod[k1] ))
    2224                 :           0 :     {
    2225                 :             :         /*  bond parity can be calculated */
    2226                 :             :         int half_parity1, half_parity2;
    2227                 :             :         /*  check whether all neighbors are defined */
    2228                 :             : 
    2229                 :             : 
    2230                 :           0 :         half_parity1 = HalfStereoBondParity( at, i, k1, nRank );
    2231                 :           0 :         half_parity2 = HalfStereoBondParity( at, n, k2, nRank );
    2232   [ #  #  #  # ]:           0 :         if (!half_parity1 || !half_parity2)
    2233                 :           0 :             return 0; /*  ranks undefined or not a stereo bond */
    2234   [ #  #  #  #  :           0 :         if (ATOM_PARITY_WELL_DEF( half_parity1 ) &&
                   #  # ]
    2235         [ #  # ]:           0 :              ATOM_PARITY_WELL_DEF( half_parity2 ))
    2236                 :             :         {
    2237                 :           0 :             parity = 2 - ( half_parity1 + half_parity2
    2238                 :           0 :                      + ( at[i].stereo_bond_z_prod[k1] < 0 ) ) % 2;
    2239                 :             :         }
    2240                 :             :         else
    2241                 :             :         {
    2242                 :           0 :             return CT_STEREOBOND_ERROR;  /*   <BRKPT> */
    2243                 :             :         }
    2244                 :             :     }
    2245                 :             :     else
    2246                 :             :     {
    2247                 :             :         /*  parity cannot be calculated: not enough info or 'unknown' */
    2248         [ #  # ]:           0 :         if (AB_PARITY_NONE != ( parity = inchi_max( at[i].parity, at[n].parity ) ))
    2249                 :             :         {
    2250                 :           0 :             parity = AB_PARITY_UNDF; /*  should not happen */
    2251                 :             :         }
    2252                 :             :     }
    2253                 :             : 
    2254                 :           0 :     return parity;
    2255                 :             : }
    2256                 :             : 
    2257                 :             : 
    2258                 :             : /****************************************************************************
    2259                 :             :  Extracted from FillSingleStereoDescriptors(...)
    2260                 :             : ****************************************************************************/
    2261                 :           0 : int GetPermutationParity( CANON_GLOBALS *pCG,
    2262                 :             :                           sp_ATOM       *at,
    2263                 :             :                           AT_RANK       nAvoidNeighbor,
    2264                 :             :                           AT_RANK       *nCanonRank )
    2265                 :             : {
    2266                 :             :     AT_RANK nNeighRank[MAX_NUM_STEREO_ATOM_NEIGH];
    2267                 :             :     int     j, k, parity;
    2268         [ #  # ]:           0 :     if (at->valence > MAX_NUM_STEREO_ATOM_NEIGH)
    2269                 :             :     {
    2270                 :           0 :         parity = -1; /*  error */
    2271                 :             :     }
    2272                 :             :     else
    2273                 :             :     {
    2274         [ #  # ]:           0 :         for (j = k = 0; j < at->valence; j++)
    2275                 :             :         {
    2276         [ #  # ]:           0 :             if (at->neighbor[j] != nAvoidNeighbor)
    2277                 :             :             {
    2278                 :           0 :                 nNeighRank[k++] = nCanonRank[(int) at->neighbor[j]];
    2279                 :             :             }
    2280                 :             :         }
    2281         [ #  # ]:           0 :         if (k)
    2282                 :             :         {
    2283                 :           0 :             parity = insertions_sort( pCG, nNeighRank, k, sizeof( nNeighRank[0] ), comp_AT_RANK );
    2284         [ #  # ]:           0 :             if (nNeighRank[0])
    2285                 :             :             {
    2286                 :           0 :                 parity = 2 - parity % 2;
    2287                 :             :             }
    2288                 :             :             else
    2289                 :             :             {
    2290                 :           0 :                 parity = 0; /*  not all ranks are known */
    2291                 :             :             }
    2292                 :             :         }
    2293                 :             :         else
    2294                 :             :         {
    2295                 :             :             /* special case: HX= with implicit H */
    2296                 :           0 :             parity = 2;
    2297                 :             :         }
    2298                 :             :     }
    2299                 :             : 
    2300                 :           0 :     return parity;
    2301                 :             : }
    2302                 :             : 
    2303                 :             : 
    2304                 :             : /****************************************************************************/
    2305                 :           0 : int GetStereoCenterParity( CANON_GLOBALS *pCG,
    2306                 :             :                            sp_ATOM       *at,
    2307                 :             :                            int           i,
    2308                 :             :                            AT_RANK       *nRank )
    2309                 :             : {
    2310                 :             :     AT_NUMB  nNeighborNumber2[MAXVAL];
    2311                 :             :     int      parity;
    2312                 :             :     int      k, num_trans;
    2313                 :             : 
    2314         [ #  # ]:           0 :     if (!at[i].parity)
    2315                 :             :     {
    2316                 :           0 :         return 0;   /*  not a stereo center                     */
    2317                 :             :     }
    2318         [ #  # ]:           0 :     if (at[i].stereo_bond_neighbor[0])
    2319                 :             :     {
    2320                 :           0 :         return -1;  /*  a stereo bond atom, not a stereo center */
    2321                 :             :     }
    2322                 :             : 
    2323   [ #  #  #  # ]:           0 :     if (ATOM_PARITY_WELL_DEF( at[i].parity ))
    2324                 :           0 :     {
    2325                 :             :         /*  number of neighbors transpositions to the sorted order is unknown. Find it. */
    2326                 :             :         /*  If parity is not well-defined then doing this is a waste of time            */
    2327                 :           0 :         int num_neigh = at[i].valence;
    2328         [ #  # ]:           0 :         for (k = 0; k < num_neigh; k++)
    2329                 :             :         {
    2330         [ #  # ]:           0 :             if (!nRank[(int) at[i].neighbor[k]])
    2331                 :           0 :                 return 0; /*  stereo at[i] does not belong to the traversed part of the structure */
    2332                 :           0 :             nNeighborNumber2[k] = k;
    2333                 :             :         }
    2334                 :           0 :         pCG->m_pNeighborsForSort = at[i].neighbor;
    2335                 :           0 :         pCG->m_pn_RankForSort = nRank;
    2336                 :           0 :         num_trans = insertions_sort( pCG, nNeighborNumber2, num_neigh, sizeof( nNeighborNumber2[0] ), CompNeighborsAT_NUMBER );
    2337                 :             : #ifndef CT_NEIGH_INCREASE
    2338                 :             :         num_trans += ( ( num_neigh*( num_neigh - 1 ) ) / 2 ) % 2;  /*  get correct parity for ascending order */
    2339                 :             : #endif
    2340                 :           0 :         parity = 2 - ( at[i].parity + num_trans ) % 2;
    2341                 :             :     }
    2342                 :             :     else
    2343                 :             :     {
    2344                 :           0 :         parity = at[i].parity;
    2345                 :             :     }
    2346                 :             : 
    2347                 :           0 :     return parity;
    2348                 :             : }
        

Generated by: LCOV version 2.0-1