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

Generated by: LCOV version 2.0-1