LCOV - code coverage report
Current view: top level - src - ichimap2.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 20.3 % 1209 245
Test Date: 2026-10-14 12:14:55 Functions: 56.7 % 30 17
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 10.9 % 1288 140

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * SPDX-License-Identifier: MIT
       3                 :             :  * Copyright (c) 2024 IUPAC and InChI Trust
       4                 :             :  */
       5                 :             : 
       6                 :             : #include <stdlib.h>
       7                 :             : #include <string.h>
       8                 :             : 
       9                 :             : #include "mode.h"
      10                 :             : #include "ichicomn.h"
      11                 :             : 
      12                 :             : #include "bcf_s.h"
      13                 :             : 
      14                 :             : #define MAP_MODE_STD  0 /* Standard approach: switch 2 neighbors */
      15                 :             : #define MAP_MODE_C2v  1 /* Check for C2v reflection leading to parity inversion */
      16                 :             : #define MAP_MODE_C2   2 /* Check for C2 rotation preserving parities */
      17                 :             : #define MAP_MODE_S4   3 /* Check for S4 rotation/reflection leading to parity inversion */
      18                 :             : /* important: MAP_MODE_STD < (MAP_MODE_C2v, MAP_MODE_C2) < MAP_MODE_S4 */
      19                 :             : 
      20                 :             : /* local prototypes */
      21                 :             : void DeAllocateForNonStereoRemoval( AT_RANK **nAtomNumberCanon1,
      22                 :             :                                     AT_RANK **nAtomNumberCanon2,
      23                 :             :                                     NEIGH_LIST **nl,
      24                 :             :                                     NEIGH_LIST **nl1, NEIGH_LIST **nl2,
      25                 :             :                                     AT_RANK **nVisited1, AT_RANK **nVisited2 );
      26                 :             : 
      27                 :             : int AllocateForNonStereoRemoval( sp_ATOM *at, int num_atoms,
      28                 :             :                                  const AT_RANK *nSymmRank, AT_RANK *nCanonRank,
      29                 :             :                                  AT_RANK **nAtomNumberCanon1,
      30                 :             :                                  AT_RANK **nAtomNumberCanon2,
      31                 :             :                                  NEIGH_LIST **nl, NEIGH_LIST **nl1, NEIGH_LIST **nl2,
      32                 :             :                                  AT_RANK **nVisited1, AT_RANK **nVisited2 );
      33                 :             : 
      34                 :             : AT_RANK GetMinNewRank( AT_RANK *nAtomRank, AT_RANK *nAtomNumb, AT_RANK nRank1 );
      35                 :             : 
      36                 :             : int BreakNeighborsTie( CANON_GLOBALS *pCG,
      37                 :             :                        sp_ATOM *at, int num_atoms, int num_at_tg, int ib, int ia,
      38                 :             :                        AT_RANK *neigh_num, int in1, int in2, int mode,
      39                 :             :                        AT_RANK **pRankStack1, AT_RANK **pRankStack2,
      40                 :             :                        AT_RANK *nTempRank, NEIGH_LIST *NeighList,
      41                 :             :                        const AT_RANK *nSymmRank, AT_RANK *nCanonRank,
      42                 :             :                        NEIGH_LIST *nl1, NEIGH_LIST *nl2, long *lNumIter );
      43                 :             : 
      44                 :             : int CheckNextSymmNeighborsAndBonds( sp_ATOM *at, AT_RANK cur1, AT_RANK cur2,
      45                 :             :                                     AT_RANK n1, AT_RANK n2,
      46                 :             :                                     AT_RANK *nAvoidCheckAtom, AT_RANK *nVisited1,
      47                 :             :                                     AT_RANK *nVisited2,
      48                 :             :                                     AT_RANK *nVisitOrd1, AT_RANK *nVisitOrd2,
      49                 :             :                                     const AT_RANK *nRank1, const AT_RANK *nRank2 );
      50                 :             : 
      51                 :             : int CreateCheckSymmPaths( sp_ATOM *at, AT_RANK prev1, AT_RANK cur1,
      52                 :             :                           AT_RANK prev2, AT_RANK cur2, AT_RANK *nAvoidCheckAtom,
      53                 :             :                           AT_RANK *nVisited1, AT_RANK *nVisited2,
      54                 :             :                           AT_RANK *nVisitOrd1, AT_RANK *nVisitOrd2,
      55                 :             :                           NEIGH_LIST *nl1, NEIGH_LIST *nl2,
      56                 :             :                           const AT_RANK *nRank1, const AT_RANK *nRank2,
      57                 :             :                           AT_RANK *nCanonRank, AT_RANK *nLength,
      58                 :             :                           int *bParitiesInverted, int mode );
      59                 :             : 
      60                 :             : int CalculatedPathsParitiesAreIdentical( CANON_GLOBALS *pCG,
      61                 :             :                                          sp_ATOM *at, int num_atoms, const AT_RANK *nSymmRank,
      62                 :             :                                          AT_RANK *nCanonRank, AT_RANK *nAtomNumberCanon, AT_RANK *nAtomNumberCanon1, AT_RANK *nAtomNumberCanon2,
      63                 :             :                                          AT_RANK *nVisited1, AT_RANK *nVisited2,
      64                 :             :                                          AT_RANK prev_sb_neigh, AT_RANK cur, AT_RANK next1, AT_RANK next2, int nNeighMode,
      65                 :             :                                          int bParitiesInverted, int mode, CANON_STAT *pCS,
      66                 :             :                                          int vABParityUnknown );
      67                 :             : 
      68                 :             : int RemoveCalculatedNonStereoBondParities( CANON_GLOBALS *pCG,
      69                 :             :                                            sp_ATOM *at,
      70                 :             :                                            int num_atoms, int num_at_tg,
      71                 :             :                                            AT_RANK **pRankStack1,
      72                 :             :                                            AT_RANK **pRankStack2,
      73                 :             :                                            AT_RANK *nTempRank, NEIGH_LIST *NeighList,
      74                 :             :                                            AT_RANK *nCanonRank,
      75                 :             :                                            const AT_RANK *nSymmRank,
      76                 :             :                                            AT_RANK *nAtomNumberCanon,
      77                 :             :                                            AT_RANK *nAtomNumberCanon1, AT_RANK *nAtomNumberCanon2,
      78                 :             :                                            NEIGH_LIST *nl,
      79                 :             :                                            NEIGH_LIST *nl1,
      80                 :             :                                            NEIGH_LIST *nl2,
      81                 :             :                                            AT_RANK *nVisited1, AT_RANK *nVisited2,
      82                 :             :                                            CANON_STAT *pCS,
      83                 :             :                                            int vABParityUnknown );
      84                 :             : 
      85                 :             : int RemoveCalculatedNonStereoCenterParities( CANON_GLOBALS *pCG,
      86                 :             :                                              sp_ATOM *at,
      87                 :             :                                              int num_atoms, int num_at_tg,
      88                 :             :                                              AT_RANK **pRankStack1,
      89                 :             :                                              AT_RANK **pRankStack2,
      90                 :             :                                              AT_RANK *nTempRank, NEIGH_LIST *NeighList,
      91                 :             :                                              AT_RANK *nCanonRank,
      92                 :             :                                              const AT_RANK *nSymmRank,
      93                 :             :                                              AT_RANK *nAtomNumberCanon,
      94                 :             :                                              AT_RANK *nAtomNumberCanon1, AT_RANK *nAtomNumberCanon2,
      95                 :             :                                              NEIGH_LIST *nl, NEIGH_LIST *nl1, NEIGH_LIST *nl2,
      96                 :             :                                              AT_RANK *nVisited1, AT_RANK *nVisited2,
      97                 :             :                                              CANON_STAT *pCS,
      98                 :             :                                              int vABParityUnknown );
      99                 :             : 
     100                 :             : int SortNeighLists3( int num_atoms,
     101                 :             :                      AT_RANK *nRank,
     102                 :             :                      NEIGH_LIST *NeighList,
     103                 :             :                      AT_RANK *nAtomNumber );
     104                 :             : 
     105                 :             : 
     106                 :             : 
     107                 :             : /****************************************************************************
     108                 :             :  *
     109                 :             :  *   Convert sorted equivalence information (nSymmRank) to ranks (nRank)
     110                 :             :  *   nSymmRank and nRank may point to the same array
     111                 :             :  *
     112                 :             :  ****************************************************************************/
     113                 :         219 : int SortedEquInfoToRanks( const AT_RANK* nSymmRank, AT_RANK* nRank, const AT_RANK* nAtomNumber, int num_atoms, int *bChanged )
     114                 :             : {
     115                 :             :     /* v. 1.05 - changed declaration of nNumDiffRanks as suggested by Burt Leland
     116                 :             :                  to avoid the problem arising on compilation with VS2015
     117                 :             : 
     118                 :             :     AT_RANK        rNew, rOld, nNumDiffRanks;*/
     119                 :             :     AT_RANK        rNew, rOld;
     120                 :         219 :     int            nNumDiffRanks = 1;
     121                 :             : 
     122                 :             : 
     123                 :         219 :     int            i, j, nNumChanges = 0, i_init;
     124                 :             : 
     125                 :         219 :     i_init = num_atoms - 1;
     126                 :             :     /* djb-rwth: fixing oss-fuzz issue #69965 */
     127         [ +  - ]:         219 :     if (i_init >= 0)
     128                 :             :     {
     129                 :         219 :         j = (int)nAtomNumber[i_init];
     130                 :         219 :         rOld = nSymmRank[j];
     131                 :         219 :         rNew = (AT_RANK)num_atoms;
     132                 :         219 :         nRank[j] = (AT_RANK)num_atoms;
     133                 :         219 :         nNumDiffRanks = 1;
     134         [ +  + ]:        1400 :         for (i = i_init; i > 0; i--)
     135                 :             :         {
     136                 :        1181 :             j = (int)nAtomNumber[i - 1];
     137                 :             : 
     138         [ +  + ]:        1181 :             if (nSymmRank[j] != rOld)
     139                 :             :             {
     140                 :        1044 :                 nNumDiffRanks++;
     141                 :        1044 :                 rNew = (AT_RANK)i;
     142                 :        1044 :                 nNumChanges += (rOld != rNew + 1);
     143                 :        1044 :                 rOld = nSymmRank[j];
     144                 :             :             }
     145                 :             : 
     146                 :        1181 :             nRank[j] = rNew;
     147                 :             :         }
     148                 :             :     }
     149         [ +  - ]:         219 :     if (bChanged)
     150                 :             :     {
     151                 :         219 :         *bChanged = ( 0 != nNumChanges );
     152                 :             :     }
     153                 :             : 
     154                 :         219 :     return nNumDiffRanks;
     155                 :             : }
     156                 :             : 
     157                 :             : 
     158                 :             : /****************************************************************************
     159                 :             :  *
     160                 :             :  *   Convert sorted ranks (nRank) to sorted equivalence information (nSymmRank)
     161                 :             :  *   nSymmRank and nRank may point to the same array
     162                 :             :  *
     163                 :             :  ****************************************************************************/
     164                 :           0 : int SortedRanksToEquInfo( AT_RANK* nSymmRank, const AT_RANK* nRank, const AT_RANK* nAtomNumber, int num_atoms )
     165                 :             : {
     166                 :             :     /* v. 1.05 - changed declaration of nNumDiffRanks as suggested by Burt Leland
     167                 :             :                  to avoid the problem arising on compilation with VS2015
     168                 :             : 
     169                 :             :     AT_RANK        rNew, rOld, nNumDiffRanks;*/
     170                 :             :     AT_RANK        rNew, rOld;
     171                 :           0 :     int nNumDiffRanks = 1;
     172                 :             : 
     173                 :             :     int            i, j;
     174                 :           0 :     for (i = 1, j = (int) nAtomNumber[0],
     175                 :           0 :           rOld = nRank[j], rNew = nSymmRank[j] = 1,
     176                 :           0 :           nNumDiffRanks = 1;
     177         [ #  # ]:           0 :             i < num_atoms;
     178                 :           0 :                         i++)
     179                 :             :     {
     180                 :           0 :         j = (int) nAtomNumber[i];
     181         [ #  # ]:           0 :         if (nRank[j] != rOld)
     182                 :             :         {
     183                 :           0 :             nNumDiffRanks++;
     184                 :           0 :             rNew = (AT_RANK) ( i + 1 );
     185                 :           0 :             rOld = nRank[j];
     186                 :             :         }
     187                 :           0 :         nSymmRank[j] = rNew;
     188                 :             :     }
     189                 :             : 
     190                 :           0 :     return nNumDiffRanks;
     191                 :             : }
     192                 :             : 
     193                 :             : 
     194                 :             : /****************************************************************************/
     195                 :         832 : void switch_ptrs( AT_RANK **p1, AT_RANK **p2 )
     196                 :             : {
     197                 :         832 :     AT_RANK *tmp = *p1;
     198                 :         832 :     *p1 = *p2;
     199                 :         832 :     *p2 = tmp;
     200                 :         832 : }
     201                 :             : 
     202                 :             : /****************************************************************************/
     203                 :             : /*  Set ranks from the products vector and previous ranks                   */
     204                 :             : /*  nRank[] and nNewRank[] should refer to different arrays for now         */
     205                 :             : /****************************************************************************/
     206                 :         219 : int SetNewRanksFromNeighLists3( CANON_GLOBALS *pCG,
     207                 :             :                                 int num_atoms,
     208                 :             :                                 NEIGH_LIST *NeighList,
     209                 :             :                                 AT_RANK *nRank,
     210                 :             :                                 AT_RANK *nNewRank,
     211                 :             :                                 AT_RANK *nAtomNumber )
     212                 :             : {
     213                 :             :     int     i, j, k, nNumDiffRanks, nNumNewRanks;
     214                 :             :     AT_RANK r1, r2;
     215                 :             : 
     216                 :             :     /*  -- nAtomNumber[] is already properly set --
     217                 :             :     for ( i = 0; i < num_atoms; i++ ) {
     218                 :             :         nAtomNumber[i] = (AT_RANK)i;
     219                 :             :     }
     220                 :             :     */
     221                 :             :     /*  set globals for qsort */
     222                 :             : 
     223                 :         219 :     pCG->m_pNeighList_RankForSort = NeighList;
     224                 :         219 :     pCG->m_pn_RankForSort = nRank;
     225                 :         219 :     nNumDiffRanks = 0;
     226                 :         219 :     nNumNewRanks = 0;
     227                 :             : 
     228                 :         219 :     memset( nNewRank, 0, num_atoms * sizeof( nNewRank[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     229                 :             : 
     230                 :             :     /*  sorting */
     231         [ +  + ]:        2189 :     for (i = 0, r1 = 1; i < num_atoms; r1++)
     232                 :             :     {
     233                 :        1970 :         j = (int)nAtomNumber[i];
     234                 :        1970 :         r2 = nRank[j];
     235         [ +  + ]:        1970 :         if (r1 == r2)
     236                 :             :         {
     237                 :        1560 :             nNewRank[j] = r2;
     238                 :        1560 :             nNumDiffRanks++;
     239                 :        1560 :             i++;
     240                 :        1560 :             continue;
     241                 :             :         }
     242                 :         410 :         r1 = r2;
     243                 :         410 :         insertions_sort_AT_NUMBERS( pCG, nAtomNumber + i, (int) r2 - i, CompNeighLists );
     244                 :             :         /*insertions_sort( nAtomNumber+i, r2-i, sizeof( nAtomNumber[0] ), CompNeighLists );*/
     245                 :         410 :         j = r2 - 1;
     246                 :         410 :         k = (int)nAtomNumber[j];
     247                 :         410 :         nNewRank[k] = r2;
     248                 :         410 :         nNumDiffRanks++;
     249         [ +  + ]:         892 :         while (j > i)
     250                 :             :         {
     251         [ +  + ]:         482 :             if (CompareNeighListLex( NeighList[(int) nAtomNumber[j - 1]],
     252                 :         482 :                 NeighList[(int) nAtomNumber[j]], nRank ))
     253                 :             :             {
     254                 :         105 :                 r2 = j;
     255                 :         105 :                 nNumDiffRanks++;
     256                 :         105 :                 nNumNewRanks++;
     257                 :             :             }
     258                 :         482 :             j--;
     259                 :         482 :             nNewRank[(int) nAtomNumber[j]] = r2;
     260                 :             :         }
     261                 :         410 :         i = r1;
     262                 :             :     }
     263                 :             : 
     264         [ +  + ]:         219 :     return nNumNewRanks ? -nNumDiffRanks : nNumDiffRanks;
     265                 :             : }
     266                 :             : 
     267                 :             : 
     268                 :             : /****************************************************************************/
     269                 :             : /*  Set ranks from the products vector and previous ranks                   */
     270                 :             : /*  When comparing neigh lists ignore ranks > max_at_no                     */
     271                 :             : /*  nRank[] and nNewRank[] should refer to different arrays for now         */
     272                 :             : /****************************************************************************/
     273                 :         123 : int SetNewRanksFromNeighLists4( CANON_GLOBALS *pCG,
     274                 :             :                                 int num_atoms,
     275                 :             :                                 NEIGH_LIST *NeighList,
     276                 :             :                                 AT_RANK *nRank,
     277                 :             :                                 AT_RANK *nNewRank,
     278                 :             :                                 AT_RANK *nAtomNumber,
     279                 :             :                                 AT_RANK nMaxAtRank )
     280                 :             : {
     281                 :             :     int     i, j, nNumDiffRanks, nNumNewRanks;
     282                 :             :     AT_RANK r1, r2;
     283                 :             :     /*  -- nAtomNumber[] is already properly set --
     284                 :             :     for ( i = 0; i < num_atoms; i++ ) {
     285                 :             :         nAtomNumber[i] = (AT_RANK)i;
     286                 :             :     }
     287                 :             :     */
     288                 :             : 
     289                 :             :     /*  set globals for CompNeighListsUpToMaxRank */
     290                 :         123 :     pCG->m_pNeighList_RankForSort = NeighList;
     291                 :         123 :     pCG->m_pn_RankForSort = nRank;
     292                 :         123 :     nNumDiffRanks = 0;
     293                 :         123 :     nNumNewRanks = 0;
     294                 :         123 :     pCG->m_nMaxAtNeighRankForSort = nMaxAtRank;
     295                 :             : 
     296                 :         123 :     memset( nNewRank, 0, num_atoms * sizeof( nNewRank[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     297                 :             : 
     298                 :             :     /*  sorting */
     299         [ +  + ]:         982 :     for (i = 0, r1 = 1; i < num_atoms; r1++)
     300                 :             :     {
     301         [ +  + ]:         859 :         if (r1 == ( r2 = nRank[j = (int) nAtomNumber[i]] ))
     302                 :             :         {
     303                 :             :             /* non-tied rank: singleton */
     304                 :         676 :             nNewRank[j] = r2;
     305                 :         676 :             nNumDiffRanks++;
     306                 :         676 :             i++;
     307                 :         676 :             continue;
     308                 :             :         }
     309                 :             :         /* tied rank r2
     310                 :             :            r2-i atoms have rank r2
     311                 :             :            next atom after them is in position r2
     312                 :             :         */
     313                 :         183 :         r1 = r2;
     314                 :             : 
     315                 :         183 :         insertions_sort_AT_NUMBERS( pCG, nAtomNumber + i,
     316                 :         183 :             (int) r2 - i, CompNeighListsUpToMaxRank );
     317                 :             :         /*insertions_sort( nAtomNumber+i, r2-i, sizeof( nAtomNumber[0] ),  CompNeighListsUpToMaxRank );*/
     318                 :             : 
     319                 :         183 :         j = r2 - 1; /* prepare cycle backward, from j to i step -1 */
     320                 :         183 :         nNewRank[(int) nAtomNumber[j]] = r2;
     321                 :         183 :         nNumDiffRanks++;
     322         [ +  + ]:         462 :         while (j > i)
     323                 :             :         {
     324         [ +  + ]:         279 :             if (CompareNeighListLexUpToMaxRank( NeighList[nAtomNumber[j - 1]],
     325                 :         279 :                 NeighList[nAtomNumber[j]], nRank, nMaxAtRank ))
     326                 :             :             {
     327                 :          24 :                 r2 = j;
     328                 :          24 :                 nNumDiffRanks++;
     329                 :          24 :                 nNumNewRanks++;
     330                 :             :             }
     331                 :         279 :             j--;
     332                 :         279 :             nNewRank[(int) nAtomNumber[j]] = r2;
     333                 :             :         }
     334                 :         183 :         i = r1;
     335                 :             :     }
     336                 :             : 
     337         [ +  + ]:         123 :     return nNumNewRanks ? -nNumDiffRanks : nNumDiffRanks;
     338                 :             : }
     339                 :             : 
     340                 :             : 
     341                 :             : /****************************************************************************/
     342                 :             : /*  Set ranks from the products vector and previous ranks                   */
     343                 :             : /*  nRank[] and nNewRank[] should refer to different arrays for now         */
     344                 :             : /****************************************************************************/
     345                 :         414 : int SetNewRanksFromNeighLists( CANON_GLOBALS *pCG,
     346                 :             :                                int num_atoms,
     347                 :             :                                NEIGH_LIST *NeighList,
     348                 :             :                                AT_RANK *nRank,
     349                 :             :                                AT_RANK *nNewRank,
     350                 :             :                                AT_RANK *nAtomNumber,
     351                 :             :                                int bUseAltSort,
     352                 :             :                                int( *comp )( const void *, const void *, void * ) )
     353                 :             : {
     354                 :             :     int     i, nNumDiffRanks, j;
     355                 :             :     AT_RANK nCurrentRank;
     356                 :             :     /*  -- nAtomNumber[] is already properly set --
     357                 :             :     for ( i = 0; i < num_atoms; i++ ) {
     358                 :             :         nAtomNumber[i] = (AT_RANK)i;
     359                 :             :     }
     360                 :             :     */
     361                 :             : 
     362                 :             :     /*  set globals for qsort */
     363                 :         414 :     pCG->m_pNeighList_RankForSort = NeighList;
     364                 :         414 :     pCG->m_pn_RankForSort = nRank;
     365                 :             : 
     366                 :             :     /*  sorting */
     367         [ +  - ]:         414 :     if (bUseAltSort & 1)
     368                 :         414 :         tsort( pCG, nAtomNumber, num_atoms, sizeof( nAtomNumber[0] ), comp /*CompNeighListRanksOrd*/ );
     369                 :             :     else
     370                 :           0 :         inchi_qsort( pCG, nAtomNumber, num_atoms, sizeof( nAtomNumber[0] ), comp /*CompNeighListRanksOrd*/ );
     371                 :             : 
     372                 :             :     /* djb-rwth: fixing oss-fuzz issue #69315 */
     373                 :         414 :     nNumDiffRanks = 1;
     374         [ +  - ]:         414 :     if (num_atoms > 0)
     375                 :             :     {
     376                 :         414 :         nCurrentRank = (AT_RANK)num_atoms;
     377                 :         414 :         j = num_atoms - 1;
     378                 :         414 :         nNewRank[(int)nAtomNumber[j]] = nCurrentRank;
     379                 :             :         
     380         [ +  + ]:        3893 :         for (i = num_atoms - 1; i > 0; i--)
     381                 :             :         {
     382                 :             :             /*  Note: CompNeighListRanks() in following line implicitly reads nRank pointed by pn_RankForSort */
     383         [ +  + ]:        3479 :             if (CompNeighListRanks(&nAtomNumber[i - 1], &nAtomNumber[i], pCG))
     384                 :             :             {
     385                 :        2668 :                 nNumDiffRanks++;
     386                 :        2668 :                 nCurrentRank = (AT_RANK)i;
     387                 :             :             }
     388                 :        3479 :             nNewRank[(int)nAtomNumber[i - 1]] = nCurrentRank;
     389                 :             :         }
     390                 :             :     }
     391                 :             : 
     392                 :         414 :     return nNumDiffRanks;
     393                 :             : }
     394                 :             : 
     395                 :             : 
     396                 :             : /****************************************************************************
     397                 :             :  Sort NeighList[] lists of neighbors according to the ranks of the neighbors
     398                 :             : ****************************************************************************/
     399                 :         327 : void SortNeighListsBySymmAndCanonRank( int num_atoms,
     400                 :             :                                        NEIGH_LIST *NeighList,
     401                 :             :                                        const AT_RANK *nSymmRank,
     402                 :             :                                        const AT_RANK *nCanonRank )
     403                 :             : {
     404                 :             :     int i;
     405         [ +  + ]:        3645 :     for (i = 0; i < num_atoms; i++)
     406                 :             :     {
     407                 :        3318 :         insertions_sort_NeighListBySymmAndCanonRank( NeighList[i], nSymmRank, nCanonRank );
     408                 :             :     }
     409                 :         327 : }
     410                 :             : 
     411                 :             : 
     412                 :             : /****************************************************************************/
     413                 :         414 : int SortNeighLists2( int num_atoms,
     414                 :             :                      AT_RANK *nRank,
     415                 :             :                      NEIGH_LIST *NeighList,
     416                 :             :                      AT_RANK *nAtomNumber )
     417                 :             : {
     418                 :             :     int k, i;
     419                 :         414 :     AT_RANK nPrevRank = 0; /* djb-rwth: ignoring LLVM warning: variable used */
     420                 :             :     /*
     421                 :             :      * on entry nRank[nAtomNumber[k]] <= nRank[nAtomNumber[k+1]]  ( k < num_atoms-1 )
     422                 :             :      *          nRank[nAtomNumber[k]] >= k+1                      ( k < num_atoms )
     423                 :             :      *          nRank[nAtomNumber[k]] == k+1 if this nRank value is not tied OR if
     424                 :             :      *                nRank[nAtomNumber[k]] < nRank[nAtomNumber[k+1]] OR if k = num_atoms-1.
     425                 :             :      *
     426                 :             :      */
     427         [ +  + ]:        4307 :     for (k = 0; k < num_atoms; k++)
     428                 :             :     {
     429                 :        3893 :         i = nAtomNumber[k];
     430                 :             : #ifdef FIX_STEREOCOUNT_ERR
     431         [ +  + ]:        3893 :         if (NeighList[i][0] > 1)
     432                 :             : #else
     433                 :             :         if (( nRank[i] != k + 1 || nRank[i] == nPrevRank ) && NeighList[i][0] > 1)
     434                 :             : #endif
     435                 :             :         {
     436                 :             :             /*  nRank[i] is tied (duplicated) */
     437                 :        2176 :             insertions_sort_NeighList_AT_NUMBERS( NeighList[i], nRank );
     438                 :             :         }
     439                 :        3893 :         nPrevRank = nRank[i]; /* djb-rwth: ignoring LLVM warning: variable used */
     440                 :             :     }
     441                 :             : 
     442                 :         414 :     return 0;
     443                 :             : }
     444                 :             : 
     445                 :             : 
     446                 :             : /****************************************************************************/
     447                 :         342 : int SortNeighLists3( int num_atoms,
     448                 :             :                      AT_RANK *nRank,
     449                 :             :                      NEIGH_LIST *NeighList,
     450                 :             :                      AT_RANK *nAtomNumber )
     451                 :             : {
     452                 :             :     int k, i;
     453                 :         342 :     AT_RANK nPrevRank = 0;
     454                 :             :     /*
     455                 :             :      * on entry nRank[nAtomNumber[k]] <= nRank[nAtomNumber[k+1]]  ( k < num_atoms-1 )
     456                 :             :      *          nRank[nAtomNumber[k]] >= k+1                      ( k < num_atoms )
     457                 :             :      *          nRank[nAtomNumber[k]] == k+1 if this nRank value is not tied OR if
     458                 :             :      *                nRank[nAtomNumber[k]] < nRank[nAtomNumber[k+1]] OR if k = num_atoms-1.
     459                 :             :      *
     460                 :             :      */
     461         [ +  + ]:        3932 :     for (k = 0; k < num_atoms; k++)
     462                 :             :     {
     463                 :        3590 :         i = nAtomNumber[k];
     464   [ +  +  +  +  :        3590 :         if (( nRank[i] != k + 1 || nRank[i] == nPrevRank ) && NeighList[i][0] > 1)
                   +  + ]
     465                 :             :         {
     466                 :             :             /*  nRank[i] is tied (duplicated) */
     467                 :         924 :             insertions_sort_NeighList_AT_NUMBERS3( NeighList[i], nRank );
     468                 :             :         }
     469                 :        3590 :         nPrevRank = nRank[i];
     470                 :             :     }
     471                 :         342 :     return 0;
     472                 :             : }
     473                 :             : 
     474                 :             : 
     475                 :             : /****************************************************************************
     476                 :             :    Differentiate2
     477                 :             :    Note: on entry nAtomNumber[] must contain a valid
     478                 :             :          transposition of num_atoms length
     479                 :             :          for example, nAtomNumber[i] = i;
     480                 :             :    Note2: this version does not calculate neighbor lists for non-tied ranks
     481                 :             : 
     482                 :             : ****************************************************************************/
     483                 :         219 : int  DifferentiateRanks2( CANON_GLOBALS *pCG,
     484                 :             :                           int num_atoms,
     485                 :             :                           NEIGH_LIST *NeighList,
     486                 :             :                           int nNumCurrRanks,
     487                 :             :                           AT_RANK *pnCurrRank,
     488                 :             :                           AT_RANK *pnPrevRank,
     489                 :             :                           AT_RANK *nAtomNumber,
     490                 :             :                           long *lNumIter,
     491                 :             :                           int bUseAltSort )
     492                 :             : {
     493                 :             :     /*int nNumPrevRanks;*/
     494                 :             : 
     495                 :             :     /*  SortNeighLists2 needs sorted ranks */
     496                 :         219 :     pCG->m_pn_RankForSort = pnCurrRank;
     497         [ +  + ]:         219 :     if (bUseAltSort & 1)
     498                 :          58 :         tsort( pCG, nAtomNumber, num_atoms, sizeof( nAtomNumber[0] ), CompRank /* CompRanksOrd*/ );
     499                 :             :     else
     500                 :         161 :         inchi_qsort( pCG, nAtomNumber, num_atoms, sizeof( nAtomNumber[0] ), CompRanksOrd );
     501                 :             : 
     502                 :             :     do
     503                 :             :     {
     504                 :         414 :         *lNumIter += 1;
     505                 :             :         /*nNumPrevRanks = nNumCurrRanks;*/
     506                 :         414 :         switch_ptrs( &pnCurrRank, &pnPrevRank );
     507                 :         414 :         SortNeighLists2( num_atoms, pnPrevRank, NeighList, nAtomNumber );
     508                 :             :         /*  the following call creates pnCurrRank out of pnPrevRank */
     509                 :         414 :         nNumCurrRanks = SetNewRanksFromNeighLists( pCG, num_atoms, NeighList, pnPrevRank, pnCurrRank, nAtomNumber,
     510                 :             :                                                  1, CompNeighListRanksOrd );
     511                 :             :     }
     512         [ +  + ]:         414 :     while ( /*nNumPrevRanks != nNumCurrRanks ||*/ memcmp( pnPrevRank, pnCurrRank, num_atoms * sizeof( pnCurrRank[0] ) ));
     513                 :             : 
     514                 :         219 :     return nNumCurrRanks;
     515                 :             : }
     516                 :             : 
     517                 :             : 
     518                 :             : /****************************************************************************
     519                 :             :   Differentiate3
     520                 :             : 
     521                 :             :  Note: on entry nAtomNumber[] must contain a valid
     522                 :             :        transposition of num_atoms length
     523                 :             :        for example, nAtomNumber[i] = i;
     524                 :             :  Note2: this version does not calculate neighbor lists for non-tied ranks
     525                 :             : ****************************************************************************/
     526                 :         148 : int  DifferentiateRanks3( CANON_GLOBALS *pCG,
     527                 :             :                           int num_atoms,
     528                 :             :                           NEIGH_LIST *NeighList,
     529                 :             :                           int nNumCurrRanks,
     530                 :             :                           AT_RANK *pnCurrRank,
     531                 :             :                           AT_RANK *pnPrevRank,
     532                 :             :                           AT_RANK *nAtomNumber,
     533                 :             :                           long *lNumIter )
     534                 :             : {
     535                 :             :     /*
     536                 :             :         static long count = 0;
     537                 :             :         count ++;
     538                 :             :         if ( count == 103 ) {
     539                 :             :             int stop=1;
     540                 :             :         }
     541                 :             :     */
     542                 :             : 
     543                 :             :     /*  SortNeighLists3 needs sorted ranks: ranks/atnumbers must have been already sorted */
     544                 :             :     do
     545                 :             :     {
     546                 :         219 :         *lNumIter += 1;
     547                 :         219 :         switch_ptrs( &pnCurrRank, &pnPrevRank );
     548                 :         219 :         SortNeighLists3( num_atoms, pnPrevRank, NeighList, nAtomNumber );
     549                 :             :         /*  the following call creates pnCurrRank out of pnPrevRank */
     550                 :         219 :         nNumCurrRanks = SetNewRanksFromNeighLists3( pCG, num_atoms, NeighList, pnPrevRank,
     551                 :             :                                                     pnCurrRank, nAtomNumber );
     552                 :             :     }
     553         [ +  + ]:         219 :     while (nNumCurrRanks < 0 /* memcmp( pnPrevRank, pnCurrRank, num_atoms*sizeof(pnCurrRank[0]) )*/);
     554                 :             : 
     555                 :         148 :     return nNumCurrRanks;
     556                 :             : }
     557                 :             : 
     558                 :             : 
     559                 :             : /****************************************************************************
     560                 :             : 
     561                 :             :   Differentiate4: ignore neighbors with rank > num_atoms
     562                 :             : 
     563                 :             :  Note: on entry nAtomNumber[] must contain a valid transposition of num_atoms length
     564                 :             :        for example, nAtomNumber[i] = i;
     565                 :             :  Note2: this version does not sort neighbor lists for non-tied ranks
     566                 :             :  ****************************************************************************/
     567                 :          99 : int  DifferentiateRanks4( CANON_GLOBALS *pCG, int num_atoms, NEIGH_LIST *NeighList,
     568                 :             :                           int nNumCurrRanks, AT_RANK *pnCurrRank, AT_RANK *pnPrevRank,
     569                 :             :                           AT_RANK *nAtomNumber, AT_RANK nMaxAtRank, long *lNumIter )
     570                 :             : {
     571                 :             :     /*
     572                 :             :         static long count = 0;
     573                 :             :         count ++;
     574                 :             :         if ( count == 103 ) {
     575                 :             :             int stop=1;
     576                 :             :         }
     577                 :             :     */
     578                 :             :     /*  SortNeighLists4 needs sorted ranks: ranks/atnumbers must have been already sorted */
     579                 :             :     do
     580                 :             :     {
     581                 :         123 :         *lNumIter += 1;
     582                 :         123 :         switch_ptrs( &pnCurrRank, &pnPrevRank );
     583                 :         123 :         SortNeighLists3( num_atoms, pnPrevRank, NeighList, nAtomNumber );
     584                 :             :         /*  the following call creates pnCurrRank out of pnPrevRank */
     585                 :         123 :         nNumCurrRanks = SetNewRanksFromNeighLists4( pCG, num_atoms, NeighList, pnPrevRank,
     586                 :             :                                                     pnCurrRank, nAtomNumber, nMaxAtRank );
     587                 :             :     }
     588         [ +  + ]:         123 :     while (nNumCurrRanks < 0 /* memcmp( pnPrevRank, pnCurrRank, num_atoms*sizeof(pnCurrRank[0]) )*/);
     589                 :             : 
     590                 :          99 :     return nNumCurrRanks;
     591                 :             : }
     592                 :             : 
     593                 :             : 
     594                 :             : /****************************************************************************
     595                 :             : 
     596                 :             :   DifferentiateBasic (sort according to ranks only)
     597                 :             : 
     598                 :             :   Note:  on entry nAtomNumber[] must contain a valid transposition of num_atoms length
     599                 :             :          for example, nAtomNumber[i] = i;
     600                 :             :   Note2: this version does not calculate neighbor lists for non-tied ranks
     601                 :             : ****************************************************************************/
     602                 :           0 : int  DifferentiateRanksBasic( CANON_GLOBALS *pCG, int num_atoms, NEIGH_LIST *NeighList,
     603                 :             :                                  int nNumCurrRanks, AT_RANK *pnCurrRank, AT_RANK *pnPrevRank,
     604                 :             :                                  AT_RANK *nAtomNumber, long *lNumIter, int bUseAltSort )
     605                 :             : {
     606                 :             :     int nNumPrevRanks;
     607                 :             : 
     608                 :             :     /*  SortNeighLists2 needs sorted ranks */
     609                 :           0 :     pCG->m_pn_RankForSort = pnCurrRank;
     610         [ #  # ]:           0 :     if (bUseAltSort & 1)
     611                 :             :     {
     612                 :           0 :         tsort( pCG, nAtomNumber, num_atoms, sizeof( nAtomNumber[0] ), CompRank );
     613                 :             :     }
     614                 :             :     else
     615                 :             :     {
     616                 :           0 :         inchi_qsort( pCG, nAtomNumber, num_atoms, sizeof( nAtomNumber[0] ), CompRank );
     617                 :             :     }
     618                 :             : 
     619                 :             :     do
     620                 :             :     {
     621                 :           0 :         *lNumIter += 1;
     622                 :           0 :         nNumPrevRanks = nNumCurrRanks;
     623                 :           0 :         switch_ptrs( &pnCurrRank, &pnPrevRank );
     624                 :           0 :         SortNeighLists2( num_atoms, pnPrevRank, NeighList, nAtomNumber );
     625                 :             :         /*  the following call creates pnCurrRank out of pnPrevRank */
     626                 :           0 :         nNumCurrRanks = SetNewRanksFromNeighLists( pCG, num_atoms, NeighList, pnPrevRank, pnCurrRank, nAtomNumber, bUseAltSort, CompNeighListRanks );
     627                 :             :     }
     628   [ #  #  #  # ]:           0 :     while (nNumPrevRanks != nNumCurrRanks || memcmp( pnPrevRank, pnCurrRank, num_atoms * sizeof( pnCurrRank[0] ) ));
     629                 :           0 :     return nNumCurrRanks;
     630                 :             : }
     631                 :             : 
     632                 :             : 
     633                 :             : /****************************************************************************
     634                 :             :  * For the purpose of mapping an atom to an atom:
     635                 :             :  * (a) find number of tied ranks
     636                 :             :  * (b) if number of tied ranks > 1 then:
     637                 :             :  *    1) find the rank for breaking a tie
     638                 :             :  *    2) allocate memory for breaking the tie if it has not been allocated
     639                 :             :  *    3) find out if atom 1 ("from") has already been mapped
     640                 :             :  * Return value:
     641                 :             :  *  < 0: error
     642                 :             :  *  = 1: has already been mapped, to tie to break
     643                 :             :  *  > 1: we need to break a tie
     644                 :             :  ****************************************************************************/
     645                 :           0 : int NumberOfTies( AT_RANK **pRankStack1,
     646                 :             :                   AT_RANK **pRankStack2,
     647                 :             :                   int length,
     648                 :             :                   int at_no1,
     649                 :             :                   int at_no2,
     650                 :             :                   AT_RANK *nNewRank,
     651                 :             :                   int *bAddStack,
     652                 :             :                   int *bMapped1 )
     653                 :             : {
     654                 :             : 
     655                 :           0 :     AT_RANK *nRank1 = *pRankStack1++;
     656                 :           0 :     AT_RANK *nAtomNumber1 = *pRankStack1++;  /*  ranks for mapping "1", "from" */
     657                 :             : 
     658                 :           0 :     AT_RANK *nRank2 = *pRankStack2++;
     659                 :           0 :     AT_RANK *nAtomNumber2 = *pRankStack2++;  /*  ranks for mapping "2", "to" */
     660                 :             : 
     661                 :             :     AT_RANK r, *pTempArray;
     662                 :             : 
     663                 :             :     int iMax, i, i1, i2;
     664                 :             : 
     665                 :           0 :     *bAddStack = 0;
     666                 :           0 :     *bMapped1 = 0;
     667                 :           0 :     *nNewRank = 0;
     668                 :           0 :     r = nRank1[at_no1];
     669                 :             : 
     670         [ #  # ]:           0 :     if (r != nRank2[at_no2])
     671                 :             :     {
     672                 :           0 :         return CT_MAPCOUNT_ERR; /*  atoms cannot be mapped onto each other: they have different ranks */ /*   <BRKPT> */
     673                 :             :     }
     674                 :           0 :     iMax = r - 1;
     675                 :             :     /*  find i1 and i2 = numbers of ranks in nRank1[] and nRank2[] equal to r:  */
     676   [ #  #  #  # ]:           0 :     for (i1 = 1; i1 <= iMax && r == nRank1[nAtomNumber1[iMax - i1]]; i1++)
     677                 :             :     {
     678                 :             :         ;
     679                 :             :     }
     680   [ #  #  #  # ]:           0 :     for (i2 = 1; i2 <= iMax && r == nRank2[nAtomNumber2[iMax - i2]]; i2++)
     681                 :             :     {
     682                 :             :         ;
     683                 :             :     }
     684         [ #  # ]:           0 :     if (i2 != i1)
     685                 :           0 :         return CT_MAPCOUNT_ERR; /*  program error: must be identical number of equal ranks */ /*   <BRKPT> */
     686                 :             :     /*  found i1 equal rank(s); preceding (smaller) non-equal rank is r-i1 */
     687                 :             :     /*  To break the tie we have to reduce the rank r to r-i1+1 */
     688                 :             : 
     689                 :             :     /************ Note *******************************
     690                 :             :      * IF ( i=r-1 && 0 <= i && i < num_atoms AND
     691                 :             :      *      nRank[nAtomNumber1[i]] == r )
     692                 :             :      * THEN:
     693                 :             :      * nRank[nAtomNumber1[i+1]] >  r; (if i+1 < num_atoms)
     694                 :             :      * nRank[nAtomNumber1[i-1]] <= r; (if i > 0)
     695                 :             :      *
     696                 :             :      * IF r = nRank[i] THEN
     697                 :             :      * nRank[nAtomNumber1[r-1]] == r
     698                 :             :      * nRank[nAtomNumber1[r-i-1]] <= nRank[nAtomNumber1[r-i]] (for 1 <= i < r )
     699                 :             :      */
     700         [ #  # ]:           0 :     if (i1 > 1)
     701                 :             :     {
     702                 :             :         /* int bAtFromHasAlreadyBeenMapped = 0; */
     703                 :           0 :         *nNewRank = r - i1 + 1;
     704                 :             :         /*  grab an existing or allocate a new array */
     705                 :             :         /*  we need 4 arrays: 2 for ranks + 2 for numbers */
     706         [ #  # ]:           0 :         for (i = 0; i < 4; i++)
     707                 :             :         {
     708         [ #  # ]:           0 :             if (i < 2)
     709                 :             :             {
     710                 :           0 :                 pTempArray = *pRankStack1;
     711   [ #  #  #  # ]:           0 :                 *bMapped1 += ( pTempArray && pTempArray[0] );
     712                 :             :             }
     713                 :             :             else
     714                 :             :             {
     715                 :           0 :                 pTempArray = *pRankStack2;
     716                 :             :             }
     717   [ #  #  #  # ]:           0 :             if (!pTempArray && !( pTempArray = (AT_RANK *) inchi_malloc( length ) ))
     718                 :           0 :                 return CT_OUT_OF_RAM;  /*  out of RAM */ /*   <BRKPT> */
     719                 :             :             /*  copy "to" contents */
     720      [ #  #  # ]:           0 :             switch (i)
     721                 :             :             {
     722                 :           0 :                 case 2:
     723                 :           0 :                     memcpy(pTempArray, nRank2, length);
     724                 :           0 :                     break;
     725                 :           0 :                 case 3:
     726                 :           0 :                     memcpy(pTempArray, nAtomNumber2, length);
     727                 :           0 :                     break;
     728                 :             :             }
     729         [ #  # ]:           0 :             if (i < 2)
     730                 :           0 :                 *pRankStack1++ = pTempArray;
     731                 :             :             else
     732                 :             :             {
     733                 :           0 :                 *pRankStack2++ = pTempArray;
     734                 :             :             }
     735                 :             :         }
     736                 :           0 :         *bAddStack = 2; /*  to break the tie we added 2 more arrays to pRankStack1 and pRankStack2 */
     737                 :             :     }
     738                 :             : 
     739                 :           0 :     return i1;
     740                 :             : }
     741                 :             : 
     742                 :             : 
     743                 :             : /****************************************************************************
     744                 :             :  *
     745                 :             :  *
     746                 :             :  *
     747                 :             :  *               Stereo Mappings
     748                 :             :  *
     749                 :             :  *
     750                 :             :  *
     751                 :             :  ****************************************************************************/
     752                 :             : 
     753                 :             :  /****************************************************************************
     754                 :             :  * Parity for a half of a stereo bond. If both halfs have the same parity
     755                 :             :  * then the bond is "trans" (E,-,1), otherwise it is "cis" (Z,+,2).
     756                 :             :  * The advantage of this approach is: The bond parity does not depend on the
     757                 :             :  * rank of the atom located on the opposite end of the stereogenic bond.
     758                 :             :  * As the result all bond parities of, for example, benzene, can be calculated
     759                 :             :  * from equivalence ranks only, without any mappings.
     760                 :             :  *
     761                 :             :  * Input: at_no1     = number of atom for which the half-bond parity is calculated
     762                 :             :  *        i_sb_neigh = ordering number of the stereo bond in at->stereo_bond_neighbor[]
     763                 :             :  *
     764                 :             :  * Returns: 0=> no parity can be found; 1=> odd parity; 2=> even parity
     765                 :             :  *
     766                 :             :  ****************************************************************************/
     767                 :           0 : int HalfStereoBondParity( sp_ATOM *at,
     768                 :             :                           int at_no1,
     769                 :             :                           int i_sb_neigh,
     770                 :             :                           const AT_RANK *nRank )
     771                 :             : {
     772                 :             :     /*
     773                 :             :        Suppose neighbors #0,#1,#2 have ranks a, b, c. Remove rank of the neighbor connected
     774                 :             :        by the stereogenic bond (NCSB) from the a, b, c list and denote the two left as r[0], r[1],
     775                 :             :        in the same order. Let iNCSB be an ordering number (0,1,or 2) of the NCSB.
     776                 :             :        Assume the neighbor connected by the stereogenic bond has infinite positive rank.
     777                 :             :        Position the half-bond so that the stereogenic bond neighbor is to the right from the atom (see below)
     778                 :             : 
     779                 :             :        Definition.
     780                 :             :        ===========
     781                 :             :                        if rank(X) != rank(Y) then Half-bond parity = (rank(X) > rank(Y)), that is,
     782                 :             :         Y
     783                 :             :          \             if ( rank(X) < rank(Y) ) then Half-bond parity is Even
     784                 :             :           C==NCSB      if ( rank(X) > rank(Y) ) then Half-bond parity is Odd
     785                 :             :          /             if ( rank(X) = rank(Y) ) then Half-bond parity cannot be defined
     786                 :             :         X
     787                 :             : 
     788                 :             :         1                          2             1
     789                 :             :          \                          \             \
     790                 :             :           C==NCSB       C==NCSB      C==NCSB       C==NCSB
     791                 :             :          /             /            /
     792                 :             :         2             1            1
     793                 :             : 
     794                 :             :         Parity = 1    Parity = 1   Parity = 2    Parity = 2
     795                 :             :         (Odd)         (Odd)       (Even) or 0   (Even) or 0
     796                 :             : 
     797                 :             :        Half-bond parity =  (iNCSB + (r[0] > r[1]) + (Atom C geometric parity))%2
     798                 :             : 
     799                 :             :        Consider the following cases to prove the formula:
     800                 :             : 
     801                 :             :        Case 1: 3 explicit neighbors
     802                 :             :        ============================
     803                 :             :        If  (1) atom's geometric parity = even (which means neighbors #0, #1, #2 are located clockwise),
     804                 :             :        and (2) neighbors other than NCSB have different ranks, then,
     805                 :             :        assuming that NCSB always has the largest (infinite) rank (this is consistent with
     806                 :             :        the assumption that implicit hydrogens have smallest ranks), we have 3 possibilities:
     807                 :             : 
     808                 :             :                                  c         a          b
     809                 :             :                                   \         \          \
     810                 :             :                                    C==a      C==b       C==c
     811                 :             :                                   /         /          /
     812                 :             :                                  b         c          a
     813                 :             : 
     814                 :             :                 iNCSB      =      0          1          2
     815                 :             :            Half-bond parity =     b>c        a<c        a>b     (0=even, 1=odd)
     816                 :             :                                r[0]>r[1]  r[0]<r[1]  r[0]>r[1]
     817                 :             :            Half-bond parity
     818                 :             :            for all 3 cases      =    (iNCSB + (r[0] > r[1]))%2
     819                 :             : 
     820                 :             :            The following slight modification will work for both odd and even geometric parity:
     821                 :             : 
     822                 :             :            Half-bond parity     =    (iNCSB + (r[0] > r[1]) + (Atom C geometric parity))%2
     823                 :             : 
     824                 :             :            even parity (0) => atom above the bond has lower rank than the atom below the bond.
     825                 :             : 
     826                 :             : 
     827                 :             :        Case 2: 2 explicit neighbors
     828                 :             :        ============================
     829                 :             :        One implicit hydrogen atom H or hydrogen isotope (implicit rank=0). Assume r[1]=0
     830                 :             : 
     831                 :             :                                  H         a            Note. The same method
     832                 :             :                                   \         \                 works for
     833                 :             :                                    C==a      C==b
     834                 :             :                                   /         /             N==a   and   a
     835                 :             :                                  b         H             /              \
     836                 :             :                                                         b                N==b
     837                 :             :                 iNCSB       =      0         1
     838                 :             :            Half-bond parity =     b>0       a<0
     839                 :             :            (r[1]=0, r[0]>0)    r[0]>r[1]  r[0]<r[1]
     840                 :             : 
     841                 :             :            Half-bond parity =  (iNCSB + (r[0] > r[1]) + (Atom C geometric parity))%2
     842                 :             : 
     843                 :             :        Case 3: 1 explicit neighbor (NCSB)
     844                 :             :        ==================================
     845                 :             :        Two implicit hydrogens, (number of neighbors on non-streogenic bonds)==0:
     846                 :             : 
     847                 :             :        Atom C geometric parity:  Even               Odd          Note. The same method
     848                 :             :                                                                        works for
     849                 :             :                                  D                  H
     850                 :             :                                   \                  \           Even   and   Odd
     851                 :             :                                    C==a               C==a
     852                 :             :                                   /                  /           H               N==a
     853                 :             :                                  H                  D             \             /
     854                 :             :                                                                    N==a        H
     855                 :             :                 iNCSB =           0                0
     856                 :             :            Half-bond parity =    (0<0)=0         (0<0)+1 = 1
     857                 :             :            (r[1]=0, r[0]=0)    r[1]<r[0]         (r[1]<r[0])+atom_parity
     858                 :             : 
     859                 :             :            Half-parity
     860                 :             :            for this case  =    (iNCSB + (r[0] > r[1]) + (Atom C geometric parity))%2
     861                 :             : 
     862                 :             :     */
     863                 :             :     int i, j, k, iNeigh, parity, at1_parity, at_no2;
     864                 :             :     AT_RANK r[MAX_NUM_STEREO_BOND_NEIGH];
     865                 :             : 
     866   [ #  #  #  # ]:           0 :     if (at[at_no1].valence > MAX_NUM_STEREO_BOND_NEIGH || ( at1_parity = at[at_no1].parity ) <= 0)
     867                 :             :     {
     868                 :           0 :         return 0;
     869                 :             :     }
     870   [ #  #  #  # ]:           0 :     if (!PARITY_WELL_DEF( at1_parity ))
     871                 :             :     {
     872   [ #  #  #  # ]:           0 :         if (PARITY_KNOWN( at1_parity ))
     873                 :             :         {
     874                 :           0 :             return at1_parity;
     875                 :             :         }
     876                 :           0 :         return -at1_parity;
     877                 :             :     }
     878   [ #  #  #  # ]:           0 :     if (0 > i_sb_neigh || i_sb_neigh >= MAX_NUM_STEREO_BOND_NEIGH)
     879                 :             :     {
     880                 :           0 :         return CT_STEREOBOND_ERROR;  /*   <BRKPT> */
     881                 :             :     }
     882         [ #  # ]:           0 :     for (i = 0; i <= i_sb_neigh; i++)
     883                 :             :     {
     884         [ #  # ]:           0 :         if (!at[at_no1].stereo_bond_neighbor[i])
     885                 :             :         {
     886                 :           0 :             return CT_STEREOBOND_ERROR;  /*   <BRKPT> */
     887                 :             :         }
     888                 :             :     }
     889                 :           0 :     at_no2 = at[at_no1].neighbor[(int) at[at_no1].stereo_bond_ord[i_sb_neigh]];
     890                 :           0 :     memset( r, 0, sizeof( r ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     891         [ #  # ]:           0 :     for (i = j = 0, iNeigh = -1; i < at[at_no1].valence; i++)
     892                 :             :     {
     893         [ #  # ]:           0 :         if (( k = (int) at[at_no1].neighbor[i] ) == at_no2)
     894                 :             :         {
     895                 :           0 :             iNeigh = i;
     896                 :             :         }
     897                 :             :         else
     898                 :             :         {
     899                 :           0 :             r[j++] = nRank[k];
     900                 :             :         }
     901                 :             :     }
     902   [ #  #  #  # ]:           0 :     if (iNeigh < 0 || iNeigh != at[at_no1].stereo_bond_ord[i_sb_neigh])
     903                 :             :     {
     904                 :           0 :         return CT_STEREOBOND_ERROR;  /*   <BRKPT> */
     905                 :             :     }
     906   [ #  #  #  #  :           0 :     if ((j > 0 && !r[0]) || (j > 1 && !r[1])) /* djb-rwth: addressing LLVM warning */
             #  #  #  # ]
     907                 :           0 :         return 0; /*  undefined ranks */
     908                 :             : 
     909   [ #  #  #  #  :           0 :     if ((j == 2 && r[0] == r[1]) || iNeigh < 0) /* djb-rwth: addressing LLVM warning */
                   #  # ]
     910                 :             :     {
     911                 :           0 :         parity = AB_PARITY_CALC;  /*  cannot calculate bond parity without additional breaking ties. */
     912                 :             :     }
     913                 :             :     else
     914                 :             :     {
     915                 :           0 :         parity = 2 - ( at[at_no1].parity + iNeigh + ( r[1] < r[0] ) ) % 2;
     916                 :             :     }
     917                 :             : 
     918                 :           0 :     return parity;
     919                 :             : }
     920                 :             : 
     921                 :             : 
     922                 :             : /****************************************************************************/
     923                 :           0 : int parity_of_mapped_half_bond( int from_at,
     924                 :             :                                 int to_at,
     925                 :             :                                 int from_neigh,
     926                 :             :                                 int to_neigh,
     927                 :             :                                 sp_ATOM *at,
     928                 :             :                                 EQ_NEIGH *pEN,
     929                 :             :                                 const AT_RANK *nCanonRankFrom,
     930                 :             :                                 const AT_RANK *nRankFrom,
     931                 :             :                                 const AT_RANK *nRankTo )
     932                 :             : {
     933                 :             :     int     i, j, k, num_neigh;
     934                 :             :     int     to_sb_neigh_ord, from_sb_neigh_ord, parity;
     935                 :             :     AT_RANK r_to[MAX_NUM_STEREO_BOND_NEIGH], at_no_to[MAX_NUM_STEREO_BOND_NEIGH];
     936                 :             :     AT_RANK r_canon_from[MAX_NUM_STEREO_BOND_NEIGH], at_no_from[MAX_NUM_STEREO_BOND_NEIGH];
     937                 :             :     AT_RANK r, r_sb_neigh;
     938                 :             : 
     939         [ #  # ]:           0 :     for (i = 0; i < MAX_NUM_STEREO_BOND_NEIGH; i++)
     940                 :             :     {
     941                 :           0 :         r_to[i] = r_canon_from[i] = 0;
     942                 :             :     }
     943                 :             : 
     944         [ #  # ]:           0 :     if (pEN)
     945                 :             :     {
     946                 :           0 :         memset( pEN, 0, sizeof( *pEN ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     947                 :             :     }
     948                 :             : 
     949                 :             :     /*  for debug only */
     950         [ #  # ]:           0 :     if (nRankFrom[from_at] != nRankTo[to_at] ||
     951         [ #  # ]:           0 :          nRankFrom[from_neigh] != nRankTo[to_neigh] ||
     952         [ #  # ]:           0 :          at[to_at].valence != at[from_at].valence)
     953                 :             :     {
     954                 :           0 :         return 0;  /*  program error: both atoms must be mapped */ /*   <BRKPT> */
     955                 :             :     }
     956                 :             : 
     957                 :           0 :     parity = PARITY_VAL( at[to_at].parity );
     958                 :           0 :     num_neigh = at[to_at].valence;
     959                 :             : 
     960   [ #  #  #  # ]:           0 :     if (num_neigh > MAX_NUM_STEREO_BOND_NEIGH || num_neigh < MIN_NUM_STEREO_BOND_NEIGH)
     961                 :             :     {
     962                 :             :         /*  2 neighbors are possible in case of stereo bond with implicit H */
     963                 :             :         /*  or a stereocenter -CHD- with an implicit H */
     964   [ #  #  #  # ]:           0 :         if (num_neigh == 1 && at[to_at].stereo_bond_neighbor[0])
     965                 :             :         {
     966                 :             :             /*  1 neighbor can happen in case of a terminal =CHD */
     967   [ #  #  #  # ]:           0 :             if (PARITY_WELL_DEF( parity ))
     968                 :             :             {
     969                 :           0 :                 return 2 - parity % 2;
     970                 :             :             }
     971                 :             :             else
     972                 :             :             {
     973         [ #  # ]:           0 :                 if (parity)
     974                 :             :                 {
     975                 :           0 :                     return parity;
     976                 :             :                 }
     977                 :             :                 else
     978                 :             :                 {
     979                 :           0 :                     return AB_PARITY_UNDF; /*  undefined parity */
     980                 :             :                 }
     981                 :             :             }
     982                 :             :         }
     983                 :           0 :         return 0;  /*  program error */ /*   <BRKPT> */
     984                 :             :     }
     985                 :             : 
     986   [ #  #  #  # ]:           0 :     if (ATOM_PARITY_KNOWN( parity ))
     987                 :             :     {
     988   [ #  #  #  # ]:           0 :         if (!ATOM_PARITY_WELL_DEF( parity ))
     989                 :             :         {
     990                 :           0 :             return parity;
     991                 :             :         }
     992                 :             :     }
     993                 :             :     else
     994                 :             :     {
     995         [ #  # ]:           0 :         if (parity)
     996                 :             :         {
     997                 :           0 :             return 0; /* parity; */
     998                 :             :         }
     999                 :             :         else
    1000                 :             :         {
    1001                 :           0 :             return 0; /* AB_PARITY_UNDF; */ /*  possibly program error: undefined parity */
    1002                 :             :         }
    1003                 :             :     }
    1004                 :             : 
    1005                 :             :     /*  locate at[to_at].stereo_bond_neighbor[] ordering numbers */
    1006   [ #  #  #  # ]:           0 :     for (i = 0, to_sb_neigh_ord = -1; i < MAX_NUM_STEREO_BONDS && ( k = (int) at[to_at].stereo_bond_neighbor[i] ); i++)
    1007                 :             :     {
    1008         [ #  # ]:           0 :         if (k == to_neigh + 1)
    1009                 :             :         {
    1010                 :           0 :             to_sb_neigh_ord = i;
    1011                 :           0 :             break;
    1012                 :             :         }
    1013                 :             :     }
    1014         [ #  # ]:           0 :     if (to_sb_neigh_ord < 0)
    1015                 :             :     {
    1016                 :           0 :         return 0;  /*  program error: not a stereo bond */ /*   <BRKPT> */
    1017                 :             :     }
    1018                 :           0 :     to_sb_neigh_ord = (int) at[to_at].stereo_bond_ord[to_sb_neigh_ord];
    1019                 :           0 :     r_sb_neigh = nRankTo[(int) at[to_at].neighbor[to_sb_neigh_ord]];
    1020         [ #  # ]:           0 :     for (i = j = 0; i < num_neigh; i++)
    1021                 :             :     {
    1022         [ #  # ]:           0 :         if (i != to_sb_neigh_ord)
    1023                 :             :         {
    1024                 :           0 :             r_to[j] = nRankTo[(int) ( at_no_to[j] = at[to_at].neighbor[i] )];
    1025         [ #  # ]:           0 :             if (r_sb_neigh == r_to[j])
    1026                 :             :             {
    1027                 :           0 :                 return 0; /*  stereo bond atoms are not fully mapped */
    1028                 :             :             }
    1029                 :           0 :             j++;
    1030                 :             :         }
    1031                 :             :     }
    1032         [ #  # ]:           0 :     if (j + 1 != num_neigh)
    1033                 :             :     {
    1034                 :           0 :         return 0; /*  program error */ /*   <BRKPT> */
    1035                 :             :     }
    1036         [ #  # ]:           0 :     if (j == 1)
    1037                 :             :     {
    1038                 :             :         /*  only one neighbor; no mapping needed */
    1039                 :           0 :         return 2 - ( parity + 1 + to_sb_neigh_ord ) % 2;
    1040                 :             :     }
    1041         [ #  # ]:           0 :     if (j != 2)
    1042                 :             :     {
    1043                 :           0 :         return 0; /*  program error: j can be only 0, 1, or 2 */ /*   <BRKPT> */ /* djb-rwth: addressing coverity ID #499526 -- refer to the first comment in this line */
    1044                 :             :     }
    1045                 :             : 
    1046         [ #  # ]:           0 :     if (r_to[0] == r_to[1])
    1047                 :             :     {
    1048                 :             :         /*  double bond neighbors need to be mapped */
    1049                 :           0 :         j = 0;
    1050                 :           0 :         from_sb_neigh_ord = -1;
    1051         [ #  # ]:           0 :         for (i = 0; i < num_neigh; i++)
    1052                 :             :         {
    1053                 :           0 :             k = at[from_at].neighbor[i];
    1054                 :           0 :             r = nRankFrom[k];
    1055         [ #  # ]:           0 :             if (r == r_sb_neigh)
    1056                 :             :             {
    1057                 :           0 :                 from_sb_neigh_ord = i;   /*  we need this value only for error-checking */
    1058                 :             :             }
    1059                 :             :             else
    1060                 :             :             {
    1061         [ #  # ]:           0 :                 if (r == r_to[0])
    1062                 :             :                 {
    1063                 :           0 :                     r_canon_from[j] = nCanonRankFrom[k];
    1064                 :           0 :                     at_no_from[j] = (AT_RANK) k;
    1065                 :           0 :                     j++;
    1066                 :             :                 }
    1067                 :             :                 else
    1068                 :             :                 {
    1069                 :           0 :                     return 0; /*  program error: unexpected rank, not fully mapped adjacent to the stereo bond atoms */ /*   <BRKPT> */
    1070                 :             :                 }
    1071                 :             :             }
    1072                 :             :         }
    1073   [ #  #  #  # ]:           0 :         if (from_sb_neigh_ord < 0 || j != 2)
    1074                 :             :         {
    1075                 :           0 :             return 0; /*  program error: rank of a neighbor not found */ /*   <BRKPT> */
    1076                 :             :         }
    1077         [ #  # ]:           0 :         if (pEN)
    1078                 :             :         {
    1079                 :             :             /*  j == 2 */
    1080                 :           0 :             pEN->to_at[0] = at_no_to[0];
    1081                 :           0 :             pEN->to_at[1] = at_no_to[1];
    1082                 :           0 :             pEN->num_to = 2;           /*  number of stored in pEN->to_at[] central atom neighbors */
    1083                 :           0 :             pEN->rank = r_to[0];     /*  mapping rank of the tied neighbors */
    1084                 :             :              /*  i := index of the smaller out of r_canon_from[1] and r_canon_from[0] */
    1085                 :           0 :             i = ( r_canon_from[1] < r_canon_from[0] );
    1086                 :           0 :             pEN->from_at = at_no_from[i];
    1087                 :           0 :             pEN->canon_rank = r_canon_from[i];
    1088                 :             :         }
    1089                 :           0 :         return -( (int) r_to[0] );
    1090                 :             :     }
    1091                 :             :     /*  double bond neighbors a mapped: r_to[0] != r_to[1] */
    1092                 :           0 :     from_sb_neigh_ord = -1;
    1093         [ #  # ]:           0 :     for (i = 0; i < num_neigh; i++)
    1094                 :             :     {
    1095                 :           0 :         k = at[from_at].neighbor[i];
    1096                 :           0 :         r = nRankFrom[k];
    1097         [ #  # ]:           0 :         if (r == r_sb_neigh)
    1098                 :             :         {
    1099                 :           0 :             from_sb_neigh_ord = i;  /*  we need this value only for error-checking */
    1100                 :             :         }
    1101                 :             :         else
    1102                 :             :         {
    1103         [ #  # ]:           0 :             if (r == r_to[0])
    1104                 :             :             {
    1105                 :           0 :                 r_canon_from[0] = nCanonRankFrom[k];
    1106                 :             :                 /* at_no_from[0]   = (AT_RANK)k; */
    1107                 :             :             }
    1108                 :             :             else
    1109                 :             :             {
    1110         [ #  # ]:           0 :                 if (r == r_to[1])
    1111                 :             :                 {
    1112                 :           0 :                     r_canon_from[1] = nCanonRankFrom[k];
    1113                 :             :                     /* at_no_from[1]   = (AT_RANK)k; */
    1114                 :             :                 }
    1115                 :             :                 else
    1116                 :             :                 {
    1117                 :           0 :                     return 0; /*  program error: unexpected rank, not fully mapped adjacent to the stereo bond atoms */ /*   <BRKPT> */
    1118                 :             :                 }
    1119                 :             :             }
    1120                 :             :         }
    1121                 :             :     }
    1122                 :             : 
    1123   [ #  #  #  #  :           0 :     if (!r_canon_from[0] || !r_canon_from[1] || from_sb_neigh_ord < 0)
                   #  # ]
    1124                 :             :     {
    1125                 :           0 :         return 0; /*  program error: neighbor rank not found */ /*   <BRKPT> */
    1126                 :             :     }
    1127                 :             : 
    1128                 :           0 :     return 2 - ( parity + to_sb_neigh_ord + ( r_canon_from[1] < r_canon_from[0] ) ) % 2;
    1129                 :             : }
    1130                 :             : 
    1131                 :             : 
    1132                 :             : /****************************************************************************/
    1133                 :           0 : int parity_of_mapped_atom2( CANON_GLOBALS *pCG,
    1134                 :             :                             int from_at,
    1135                 :             :                             int to_at,
    1136                 :             :                             const sp_ATOM *at,
    1137                 :             :                             EQ_NEIGH *pEN,
    1138                 :             :                             const AT_RANK *nCanonRankFrom,
    1139                 :             :                             const AT_RANK *nRankFrom,
    1140                 :             :                             const AT_RANK *nRankTo )
    1141                 :             : {
    1142                 :             :     AT_RANK nNeighRankFrom[4], nNeighNumberFrom[4], nNeighRankTo[4], nNeighNumberTo[4];
    1143                 :             :     AT_RANK nNeighRankFromCanon[4], nNeighRankToCanon[4];
    1144                 :             :     int     i, j, k, num_neigh;
    1145                 :           0 :     int     r1, r2, r, r_canon_from_min, neigh_canon_from_min = 0, r_canon_from; /* djb-rwth: proper initialisation required */
    1146                 :             :     int     num_trans_to, num_trans_from, neigh1, neigh2; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1147                 :             : 
    1148                 :           0 :     num_neigh = at[to_at].valence;
    1149                 :             : 
    1150         [ #  # ]:           0 :     if (pEN)
    1151                 :             :     {
    1152                 :           0 :         memset( pEN, 0, sizeof( *pEN ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    1153                 :             :     }
    1154                 :             : 
    1155                 :             :     /*  for debug only */
    1156         [ #  # ]:           0 :     if (nRankFrom[from_at] != nRankTo[to_at])
    1157                 :             :     {
    1158                 :           0 :         return 0;  /*  program error */ /*   <BRKPT> */
    1159                 :             :     }
    1160   [ #  #  #  # ]:           0 :     if (num_neigh > MAX_NUM_STEREO_ATOM_NEIGH || num_neigh < 2)
    1161                 :             :     {
    1162                 :             :         /*  2 neighbors are possible in case of stereo bond with implicit H */
    1163                 :             :         /*  or a stereocenter >CHD with two implicit H */
    1164         [ #  # ]:           0 :         if (num_neigh == 1)
    1165                 :             :         {
    1166                 :             :             /*  1 neighbor can happen in case of a terminal -CHDT or =CHD */
    1167         [ #  # ]:           0 :             if (at[to_at].parity)
    1168                 :             :             {
    1169                 :           0 :                 return at[to_at].parity;
    1170                 :             :             }
    1171                 :             :             else
    1172                 :             :             {
    1173                 :           0 :                 return AB_PARITY_UNDF; /*  undefined parity */
    1174                 :             :             }
    1175                 :             :         }
    1176                 :           0 :         return 0;  /*  program error */ /*   <BRKPT> */
    1177                 :             :     }
    1178         [ #  # ]:           0 :     for (i = 0; i < num_neigh; i++)
    1179                 :             :     { /*  initialization of locals */
    1180                 :           0 :         nNeighNumberTo[i] =
    1181                 :           0 :             nNeighNumberFrom[i] = i;
    1182                 :           0 :         nNeighRankTo[i] = nRankTo[(int) at[to_at].neighbor[i]];       /* mapping rank */
    1183                 :           0 :         nNeighRankFrom[i] = nRankFrom[j = (int) at[from_at].neighbor[i]]; /* mapping rank */
    1184                 :           0 :         nNeighRankFromCanon[i] = nCanonRankFrom[j];                     /* canonical number */
    1185                 :             :     }
    1186                 :             : 
    1187                 :           0 :     pCG->m_pn_RankForSort = nNeighRankFrom;
    1188                 :           0 :     pCG->m_nNumCompNeighborsRanksCountEql = 0; /*  sort mapping ranks-from */
    1189                 :           0 :     num_trans_from = insertions_sort( pCG, nNeighNumberFrom, num_neigh, sizeof( nNeighNumberFrom[0] ), CompNeighborsRanksCountEql ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1190                 :             : 
    1191         [ #  # ]:           0 :     if (pCG->m_nNumCompNeighborsRanksCountEql)
    1192                 :             :     {
    1193                 :             :         /*  At least 2 neighbors have equal mapping ranks (are tied). */
    1194                 :             :         /*  Find tied from-neighbors with minimal canonical rank (nCanonRankFrom[]) */
    1195                 :           0 :         r_canon_from_min = MAX_ATOMS + 1; /*  max possible rank + 1 */
    1196         [ #  # ]:           0 :         for (i = 1, r = 0, r1 = nNeighRankFrom[neigh1 = nNeighNumberFrom[0]]; i < num_neigh; i++, r1 = r2, neigh1 = neigh2)
    1197                 :             :         {
    1198                 :           0 :             r2 = nNeighRankFrom[neigh2 = nNeighNumberFrom[i]];
    1199         [ #  # ]:           0 :             if (r2 == r1)
    1200                 :             :             {
    1201                 :             :                 /*  found neighbors with tied ranks */
    1202         [ #  # ]:           0 :                 if (r != r2)
    1203                 :             :                 {
    1204                 :             :                      /*  the 1st pair of neighbor with this rank */
    1205                 :           0 :                     r = r2;
    1206         [ #  # ]:           0 :                     if (( r_canon_from = nNeighRankFromCanon[neigh1] ) < r_canon_from_min)
    1207                 :             :                     {
    1208                 :           0 :                         r_canon_from_min = r_canon_from; /*  min canon rank */
    1209                 :           0 :                         neigh_canon_from_min = neigh1;       /*  neighbor number */
    1210                 :             :                     }
    1211                 :             :                 }
    1212         [ #  # ]:           0 :                 if (( r_canon_from = nNeighRankFromCanon[neigh2] ) < r_canon_from_min)
    1213                 :             :                 {
    1214                 :           0 :                     r_canon_from_min = r_canon_from;
    1215                 :           0 :                     neigh_canon_from_min = neigh2;
    1216                 :             :                 }
    1217                 :             :             }
    1218                 :             :         }
    1219         [ #  # ]:           0 :         if (r)
    1220                 :             :         {
    1221                 :             :             /*  neighbors with tied ranks have been found => parity cannot be determined without additional mapping */
    1222                 :             :             /*  find to-neighbors on which neigh_canon_from_min can be mapped */
    1223                 :           0 :             r1 = nNeighRankFrom[neigh_canon_from_min];
    1224         [ #  # ]:           0 :             if (pEN)
    1225                 :             :             {
    1226         [ #  # ]:           0 :                 for (i = j = 0; i < num_neigh; i++)
    1227                 :             :                 {
    1228         [ #  # ]:           0 :                     if (r1 == nNeighRankTo[i])
    1229                 :             :                     {
    1230                 :           0 :                         pEN->to_at[j++] = at[to_at].neighbor[i];
    1231                 :             :                     }
    1232                 :             :                 }
    1233                 :           0 :                 insertions_sort( pCG, pEN->to_at, j, sizeof( pEN->to_at[0] ), CompRanksInvOrd );
    1234                 :           0 :                 pEN->num_to = j;  /*  number of stored in pEN->to_at[] central atom neighbors */
    1235                 :           0 :                 pEN->from_at = at[from_at].neighbor[neigh_canon_from_min]; /*  neighbor with min. canon number */
    1236                 :           0 :                 pEN->rank = r1; /*  mapping rank of the tied neighbors */
    1237                 :           0 :                 pEN->canon_rank = r_canon_from_min;  /*  canon. rank of the pEN->from_at */
    1238                 :             :             }
    1239                 :             :             else
    1240                 :             :             {
    1241                 :             :                 /*  debug only */
    1242         [ #  # ]:           0 :                 for (i = j = 0; i < num_neigh; i++)
    1243                 :             :                 {
    1244         [ #  # ]:           0 :                     if (r1 == nNeighRankTo[i])
    1245                 :             :                     {
    1246                 :           0 :                         j++;
    1247                 :             :                     }
    1248                 :             :                 }
    1249                 :             :             }
    1250                 :             :             /*  debug only */
    1251   [ #  #  #  #  :           0 :             if (j <= 1 || !r1 || r_canon_from_min > MAX_ATOMS)
                   #  # ]
    1252                 :             :             {
    1253                 :           0 :                 return 0; /*  program error */ /*   <BRKPT> */
    1254                 :             :             }
    1255                 :           0 :             return -r; /*  means parity cannot be determined */
    1256                 :             :         }
    1257                 :           0 :         return 0; /* program error */
    1258                 :             :     }
    1259                 :             : 
    1260                 :             :     /*  All neighbors have different mapping ranks; */
    1261                 :             :     /*  therefore no additional mapping of the neighbors is necessary */
    1262   [ #  #  #  # ]:           0 :     if (!ATOM_PARITY_WELL_DEF( at[to_at].parity ))
    1263                 :             :     {
    1264                 :           0 :         return at[to_at].parity; /*  unknown parity or cannot be determined */
    1265                 :             :     }
    1266                 :             : 
    1267                 :           0 :     pCG->m_pn_RankForSort = nNeighRankTo;
    1268                 :           0 :     num_trans_to = insertions_sort( pCG, nNeighNumberTo, num_neigh, sizeof( nNeighNumberTo[0] ), CompNeighborsRanksCountEql );
    1269                 :             : 
    1270                 :             :     /*  Map canonical ranks of neighbors. Mapped on each other "to" and "from" atoms have equal mapping ranks */
    1271         [ #  # ]:           0 :     for (i = 0; i < num_neigh; i++)
    1272                 :             :     {
    1273         [ #  # ]:           0 :         if (nNeighRankTo[j = nNeighNumberTo[i]] != nNeighRankFrom[k = nNeighNumberFrom[i]])
    1274                 :             :         {
    1275                 :           0 :             return 0; /*  program error: mapping ranks not equal, from_at neigborhood cannot be mapped on to_at neighbood. */ /*   <BRKPT> */
    1276                 :             :         }
    1277                 :           0 :         nNeighRankToCanon[j] = nNeighRankFromCanon[k]; /*  potential problem: other atom(s) may have same mapping rank and */
    1278                 :             :                                                        /*  different canon. rank(s). */
    1279                 :             :         /*  we may save some memory by eliminating nNeighRankFromCanon[]: */
    1280                 :             :         /*  nNeighRankToCanon[j] = nCanonRankFrom[at[from_at].neighbor[k]] */
    1281                 :             :     }
    1282                 :             : 
    1283                 :           0 :     pCG->m_pn_RankForSort = nNeighRankToCanon;
    1284                 :           0 :     num_trans_to += insertions_sort( pCG, nNeighNumberTo, num_neigh, sizeof( nNeighNumberTo[0] ), CompNeighborsRanksCountEql );
    1285                 :             : #ifndef CT_NEIGH_INCREASE
    1286                 :             :     num_trans_to += ( ( num_neigh*( num_neigh - 1 ) ) / 2 ) % 2;  /*  get correct parity for ascending order of canon. numbers */
    1287                 :             : #endif
    1288                 :             : 
    1289                 :           0 :     return 2 - ( num_trans_to + at[to_at].parity ) % 2;
    1290                 :             : }
    1291                 :             : 
    1292                 :             : /****************************************************************************
    1293                 :             : 
    1294                 :             :    Phase II: map canonicaly numbrered structure onto itself
    1295                 :             :              to obtain a minimal or maximal stereo part of the CT
    1296                 :             : 
    1297                 :             : ****************************************************************************/
    1298                 :             : 
    1299                 :         367 : int ClearPreviousMappings( AT_RANK **pRankStack1 )
    1300                 :             : {
    1301                 :             :     int i;
    1302         [ +  + ]:         753 :     for (i = 0; pRankStack1[i]; i++)
    1303                 :             :     {
    1304                 :         386 :         pRankStack1[i][0] = 0;
    1305                 :             :     }
    1306                 :             : 
    1307                 :         367 :     return i;
    1308                 :             : }
    1309                 :             : 
    1310                 :             : 
    1311                 :             : /****************************************************************************
    1312                 :             :   map one atom ("from") onto another ("to"): untie their
    1313                 :             :   mapping ranks if they are tied.
    1314                 :             : ****************************************************************************/
    1315                 :           0 : int map_an_atom2( CANON_GLOBALS *pCG,
    1316                 :             :                   int num_atoms,
    1317                 :             :                   int num_max,
    1318                 :             :                   int at_no1/*from*/,
    1319                 :             :                   int at_no2/*to*/,
    1320                 :             :                   AT_RANK *nTempRank,
    1321                 :             :                   int nNumMappedRanks,
    1322                 :             :                   int *pnNewNumMappedRanks,
    1323                 :             :                   CANON_STAT *pCS,
    1324                 :             :                   NEIGH_LIST    *NeighList,
    1325                 :             :                   AT_RANK  **pRankStack1,
    1326                 :             :                   AT_RANK  **pRankStack2,
    1327                 :             :                   int *bAddStack )
    1328                 :             : {
    1329                 :             :     AT_RANK *nRank1, *nAtomNumber1;  /*  ranks for mapping "1", "from" */
    1330                 :             :     AT_RANK *nRank2, *nAtomNumber2;  /*  ranks for mapping "2", "to" */
    1331                 :           0 :     AT_RANK *nNewRank1 = NULL, *nNewAtomNumber1 = NULL;  /*  ranks for mapping "1", "from" */
    1332                 :           0 :     AT_RANK *nNewRank2 = NULL, *nNewAtomNumber2 = NULL;  /*  ranks for mapping "2", "to" */
    1333                 :           0 :     int     length = num_max * sizeof( AT_RANK );
    1334                 :             :     int     nNewNumRanks2, nNewNumRanks1;
    1335                 :             :     int     i, bAtFromHasAlreadyBeenMapped, nNumTies;
    1336                 :             :     AT_RANK nNewRank;
    1337                 :             : 
    1338                 :           0 :     nNumTies = NumberOfTies( pRankStack1, pRankStack2, length, at_no1, at_no2, &nNewRank, bAddStack, &bAtFromHasAlreadyBeenMapped );
    1339                 :             : 
    1340   [ #  #  #  # ]:           0 :     if (RETURNED_ERROR( nNumTies ))
    1341                 :             :     {
    1342                 :           0 :         return nNumTies;  /*  error */
    1343                 :             :     }
    1344                 :             : 
    1345                 :           0 :     nRank1 = *pRankStack1++;
    1346                 :           0 :     nAtomNumber1 = *pRankStack1++;  /*  ranks for mapping "1", "from" */
    1347                 :             : 
    1348                 :           0 :     nRank2 = *pRankStack2++;
    1349                 :           0 :     nAtomNumber2 = *pRankStack2++;  /*  ranks for mapping "2", "to" */
    1350                 :             : 
    1351         [ #  # ]:           0 :     if (nNumTies > 1)
    1352                 :             :     {
    1353                 :             : 
    1354                 :           0 :         nNewRank1 = *pRankStack1++;
    1355                 :           0 :         nNewAtomNumber1 = *pRankStack1++;  /*  ranks for mapping "1", "from" */
    1356                 :             : 
    1357                 :           0 :         nNewRank2 = *pRankStack2++;
    1358                 :           0 :         nNewAtomNumber2 = *pRankStack2++;  /*  ranks for mapping "2", "to" */
    1359                 :             :         /*  break a tie for "to" */
    1360                 :           0 :         memcpy(nNewRank2, nRank2, length);
    1361                 :           0 :         memcpy(nNewAtomNumber2, nAtomNumber2, length);
    1362                 :           0 :         nNewRank2[at_no2] = nNewRank;
    1363                 :           0 :         nNewNumRanks2 = DifferentiateRanks2( pCG, num_atoms, NeighList,
    1364                 :             :                                          nNumMappedRanks, nNewRank2, nTempRank,
    1365                 :             :                                          nNewAtomNumber2, &pCS->lNumNeighListIter, 1 );
    1366                 :           0 :         pCS->lNumBreakTies++;
    1367                 :             : 
    1368                 :             :         /*  Check whether the old mapping can be reused */
    1369   [ #  #  #  # ]:           0 :         if (2 == bAtFromHasAlreadyBeenMapped && nNewRank == nNewRank1[at_no1])
    1370                 :             :         {
    1371         [ #  # ]:           0 :             for (i = 0; i < num_atoms; i++)
    1372                 :             :             {
    1373         [ #  # ]:           0 :                 if (nNewRank1[nNewAtomNumber1[i]] != nNewRank2[nNewAtomNumber2[i]])
    1374                 :             :                 {
    1375                 :           0 :                     bAtFromHasAlreadyBeenMapped = 0; /*  It cannot. */
    1376                 :           0 :                     break;
    1377                 :             :                 }
    1378                 :             :             }
    1379                 :             :         }
    1380                 :             :         else
    1381                 :             :         {
    1382                 :           0 :             bAtFromHasAlreadyBeenMapped = 0;
    1383                 :             :         }
    1384         [ #  # ]:           0 :         if (2 != bAtFromHasAlreadyBeenMapped)
    1385                 :             :         {
    1386                 :             :             /*  break a tie for "from" */
    1387         [ #  # ]:           0 :             for (i = 0; pRankStack1[i]; i++)
    1388                 :             :             {
    1389                 :           0 :                 pRankStack1[i][0] = 0;
    1390                 :             :             }
    1391                 :           0 :             memcpy(nNewRank1, nRank1, length);
    1392                 :           0 :             memcpy(nNewAtomNumber1, nAtomNumber1, length);  /* GPF: bad nAtomNumber1 */
    1393                 :           0 :             nNewRank1[at_no1] = nNewRank;
    1394                 :           0 :             nNewNumRanks1 = DifferentiateRanks2( pCG, num_atoms, NeighList,
    1395                 :             :                                              nNumMappedRanks, nNewRank1, nTempRank,
    1396                 :             :                                              nNewAtomNumber1, &pCS->lNumNeighListIter, 1 );
    1397                 :           0 :             pCS->lNumBreakTies++;
    1398                 :             :         }
    1399                 :             :         else
    1400                 :             :         {
    1401                 :           0 :             nNewNumRanks1 = nNewNumRanks2;
    1402                 :             :         }
    1403                 :             : 
    1404         [ #  # ]:           0 :         if (nNewNumRanks1 != nNewNumRanks2)
    1405                 :           0 :             return CT_MAPCOUNT_ERR; /*  program error */ /*   <BRKPT> */
    1406                 :           0 :         *pnNewNumMappedRanks = nNewNumRanks2;
    1407                 :             :         /*  debug only */
    1408         [ #  # ]:           0 :         for (i = 0; i < num_atoms; i++)
    1409                 :             :         {
    1410         [ #  # ]:           0 :             if (nNewRank1[nNewAtomNumber1[i]] != nNewRank2[nNewAtomNumber2[i]])
    1411                 :             :             {
    1412                 :           0 :                 return CT_MAPCOUNT_ERR; /*  program error */ /*   <BRKPT> */
    1413                 :             :             }
    1414                 :             :         }
    1415                 :             :     }
    1416                 :             :     else
    1417                 :             :     {
    1418                 :           0 :         *pnNewNumMappedRanks = nNumMappedRanks;
    1419                 :             :     }
    1420                 :             : 
    1421         [ #  # ]:           0 :     return ( nNewRank1 ) ? nNewRank1[at_no1] : nRank1[at_no1]; /*  mapping rank value */
    1422                 :             : }
    1423                 :             : 
    1424                 :             : 
    1425                 :             : /****************************************************************************/
    1426                 :           0 : int might_change_other_atom_parity( sp_ATOM *at,
    1427                 :             :                                     int num_atoms,
    1428                 :             :                                     int at_no,
    1429                 :             :                                     AT_RANK *nRank2,
    1430                 :             :                                     AT_RANK *nRank1 )
    1431                 :             : {
    1432                 :             :     int     i, j, neighbor_no;
    1433         [ #  # ]:           0 :     for (i = 0; i < num_atoms; i++)
    1434                 :             :     {
    1435         [ #  # ]:           0 :         if (nRank2[i] != nRank1[i])
    1436                 :             :         {
    1437         [ #  # ]:           0 :             if (i != at_no /*&& ATOM_PARITY_WELL_DEF(at[i].parity)*/
    1438         [ #  # ]:           0 :                 && at[i].bHasStereoOrEquToStereo
    1439         [ #  # ]:           0 :                 && !( at[i].stereo_atom_parity & KNOWN_PARITIES_EQL )
    1440         [ #  # ]:           0 :                 && !at[i].stereo_bond_neighbor[0]
    1441                 :             :                 )
    1442                 :             :             {
    1443                 :             : 
    1444                 :           0 :                 return 1; /*  may have changed stereo atoms order */
    1445                 :             :             }
    1446         [ #  # ]:           0 :             for (j = 0; j < at[i].valence; j++)
    1447                 :             :             {
    1448                 :           0 :                 neighbor_no = at[i].neighbor[j];
    1449         [ #  # ]:           0 :                 if (neighbor_no != at_no
    1450                 :             :                      /*&& ATOM_PARITY_WELL_DEF(at[neighbor_no].parity)*/
    1451         [ #  # ]:           0 :                      && at[neighbor_no].bHasStereoOrEquToStereo
    1452         [ #  # ]:           0 :                      && !( at[neighbor_no].stereo_atom_parity & KNOWN_PARITIES_EQL )
    1453         [ #  # ]:           0 :                      && !at[neighbor_no].stereo_bond_neighbor[0]
    1454                 :             :                    )
    1455                 :             :                 {
    1456                 :           0 :                     return 1; /*  may have changed stereo atom parity */
    1457                 :             :                 }
    1458                 :             :             }
    1459                 :             :         }
    1460                 :             :     }
    1461                 :             : 
    1462                 :           0 :     return 0;
    1463                 :             : }
    1464                 :             : 
    1465                 :             : 
    1466                 :             : /****************************************************************************/
    1467                 :             : #if ( REMOVE_CALC_NONSTEREO == 1 ) /* { */
    1468                 :             : /****************************************************************************/
    1469                 :         218 : void DeAllocateForNonStereoRemoval( AT_RANK **nAtomNumberCanon1,
    1470                 :             :                                     AT_RANK **nAtomNumberCanon2,
    1471                 :             :                                     NEIGH_LIST **nl,
    1472                 :             :                                     NEIGH_LIST **nl1,
    1473                 :             :                                     NEIGH_LIST **nl2,
    1474                 :             :                                     AT_RANK **nVisited1,
    1475                 :             :                                     AT_RANK **nVisited2 )
    1476                 :             : {
    1477         [ +  + ]:         218 :     if (*nAtomNumberCanon1)
    1478                 :             :     {
    1479         [ +  - ]:         109 :         inchi_free( *nAtomNumberCanon1 );
    1480                 :         109 :         *nAtomNumberCanon1 = NULL;
    1481                 :             :     }
    1482         [ +  + ]:         218 :     if (*nAtomNumberCanon2)
    1483                 :             :     {
    1484         [ +  - ]:         109 :         inchi_free( *nAtomNumberCanon2 );
    1485                 :         109 :         *nAtomNumberCanon2 = NULL;
    1486                 :             :     }
    1487         [ +  + ]:         218 :     if (*nl)
    1488                 :             :     {
    1489                 :         109 :         FreeNeighList( *nl );
    1490                 :         109 :         *nl = 0;
    1491                 :             :     }
    1492         [ +  + ]:         218 :     if (*nl1)
    1493                 :             :     {
    1494                 :         109 :         FreeNeighList( *nl1 );
    1495                 :         109 :         *nl1 = 0;
    1496                 :             :     }
    1497         [ +  + ]:         218 :     if (*nl2)
    1498                 :             :     {
    1499                 :         109 :         FreeNeighList( *nl2 );
    1500                 :         109 :         *nl2 = 0;
    1501                 :             :     }
    1502         [ +  + ]:         218 :     if (*nVisited1)
    1503                 :             :     {
    1504         [ +  - ]:         109 :         inchi_free( *nVisited1 );
    1505                 :         109 :         *nVisited1 = NULL;
    1506                 :             :     }
    1507         [ +  + ]:         218 :     if (*nVisited2)
    1508                 :             :     {
    1509         [ +  - ]:         109 :         inchi_free( *nVisited2 );
    1510                 :         109 :         *nVisited2 = NULL;
    1511                 :             :     }
    1512                 :         218 : }
    1513                 :             : 
    1514                 :             : 
    1515                 :             : /****************************************************************************/
    1516                 :         109 : int AllocateForNonStereoRemoval( sp_ATOM *at,
    1517                 :             :                                  int num_atoms,
    1518                 :             :                                  const AT_RANK *nSymmRank,
    1519                 :             :                                  AT_RANK *nCanonRank,
    1520                 :             :                                  AT_RANK **nAtomNumberCanon1,
    1521                 :             :                                  AT_RANK **nAtomNumberCanon2,
    1522                 :             :                                  NEIGH_LIST **nl,
    1523                 :             :                                  NEIGH_LIST **nl1,
    1524                 :             :                                  NEIGH_LIST **nl2,
    1525                 :             :                                  AT_RANK **nVisited1,
    1526                 :             :                                  AT_RANK **nVisited2 )
    1527                 :             : {
    1528                 :         109 :     DeAllocateForNonStereoRemoval( nAtomNumberCanon1, nAtomNumberCanon2, nl, nl1, nl2, nVisited1, nVisited2 );
    1529                 :         109 :     *nAtomNumberCanon1 = (AT_RANK *) inchi_malloc( num_atoms * sizeof( **nAtomNumberCanon1 ) );
    1530                 :         109 :     *nAtomNumberCanon2 = (AT_RANK *) inchi_malloc( num_atoms * sizeof( **nAtomNumberCanon2 ) );
    1531                 :         109 :     *nl = CreateNeighList( num_atoms, num_atoms, at, 0, NULL );
    1532                 :         109 :     *nl1 = CreateNeighList( num_atoms, num_atoms, at, 0, NULL );
    1533                 :         109 :     *nl2 = CreateNeighList( num_atoms, num_atoms, at, 0, NULL );
    1534                 :         109 :     *nVisited1 = (AT_RANK *) inchi_malloc( num_atoms * sizeof( **nVisited1 ) );
    1535                 :         109 :     *nVisited2 = (AT_RANK *) inchi_malloc( num_atoms * sizeof( **nVisited2 ) );
    1536                 :             : 
    1537   [ +  -  +  -  :         109 :     if (!*nl || !*nl1 || !*nl2 || !*nVisited1 || !*nVisited2 || !*nAtomNumberCanon1 || !*nAtomNumberCanon2)
          +  -  +  -  +  
             -  +  -  -  
                      + ]
    1538                 :             :     {
    1539                 :           0 :         DeAllocateForNonStereoRemoval( nAtomNumberCanon1, nAtomNumberCanon2, nl, nl1, nl2, nVisited1, nVisited2 );
    1540                 :           0 :         return 0;
    1541                 :             :     }
    1542                 :             :     /*  Sort neighbors according to symm. ranks (primary key) and canon. ranks (secondary key), in descending order */
    1543                 :         109 :     SortNeighListsBySymmAndCanonRank( num_atoms, *nl, nSymmRank, nCanonRank );
    1544                 :         109 :     SortNeighListsBySymmAndCanonRank( num_atoms, *nl1, nSymmRank, nCanonRank );
    1545                 :         109 :     SortNeighListsBySymmAndCanonRank( num_atoms, *nl2, nSymmRank, nCanonRank );
    1546                 :             : 
    1547                 :         109 :     return 1;
    1548                 :             : }
    1549                 :             : 
    1550                 :             : 
    1551                 :             : /****************************************************************************/
    1552                 :           0 : AT_RANK GetMinNewRank( AT_RANK *nAtomRank, AT_RANK *nAtomNumb, AT_RANK nRank1 )
    1553                 :             : {
    1554                 :             :     int i;
    1555                 :           0 :     AT_RANK nRank2 = 0;
    1556   [ #  #  #  # ]:           0 :     for (i = (int) nRank1 - 1; 0 <= i && nRank1 == ( nRank2 = nAtomRank[(int) nAtomNumb[i]] ); i--)
    1557                 :             :     {
    1558                 :             :         ;
    1559                 :             :     }
    1560         [ #  # ]:           0 :     if (i >= 0)
    1561                 :             :     {
    1562                 :           0 :         nRank2++;
    1563                 :             :     }
    1564                 :             :     else
    1565                 :             :     {
    1566                 :           0 :         nRank2 = 1;
    1567                 :             :     }
    1568                 :             : 
    1569                 :           0 :     return nRank2;
    1570                 :             : }
    1571                 :             : 
    1572                 :             : 
    1573                 :             : /****************************************************************************/
    1574                 :           0 : int BreakNeighborsTie( CANON_GLOBALS *pCG,
    1575                 :             :                        sp_ATOM *at,
    1576                 :             :                        int num_atoms,
    1577                 :             :                        int num_at_tg,
    1578                 :             :                        int ib,
    1579                 :             :                        int ia,
    1580                 :             :                        AT_RANK *neigh_num,
    1581                 :             :                        int in1,
    1582                 :             :                        int in2,
    1583                 :             :                        int mode,
    1584                 :             :                        AT_RANK **pRankStack1,
    1585                 :             :                        AT_RANK **pRankStack2,
    1586                 :             :                        AT_RANK *nTempRank,
    1587                 :             :                        NEIGH_LIST *NeighList,
    1588                 :             :                        const AT_RANK *nSymmRank,
    1589                 :             :                        AT_RANK *nCanonRank,
    1590                 :             :                        NEIGH_LIST *nl1,
    1591                 :             :                        NEIGH_LIST *nl2,
    1592                 :             :                        long *lNumIter )
    1593                 :             : {
    1594                 :             :     AT_RANK nRank1, nRank2;
    1595                 :             :     int     nNumDiffRanks, nNumDiffRanks1, nNumDiffRanks2, i;
    1596                 :           0 :     int n1 = (int) neigh_num[in1];
    1597                 :           0 :     int n2 = (int) neigh_num[in2];
    1598                 :           0 :     int other_neigh[2] = {0}, other_neig_ord[2] = {0}, num_other_neigh; /* djb-rwth: initialisations added */
    1599                 :             : 
    1600                 :             :     /*  asymmetric calculation */
    1601                 :             : 
    1602   [ #  #  #  #  :           0 :     if ((mode == MAP_MODE_S4  && in1) || /* for S4 we need only (in1,in2) = (0,1) (0,2) (0,3) pairs of neighbors */
                   #  # ]
    1603   [ #  #  #  # ]:           0 :          (mode != MAP_MODE_STD && at[ia].valence != MAX_NUM_STEREO_ATOM_NEIGH) ||
    1604         [ #  # ]:           0 :          (mode != MAP_MODE_STD && nSymmRank[n1] != nSymmRank[n2])) /* djb-rwth: addressing LLVM warning */
    1605                 :             :     {
    1606                 :           0 :         return 0;
    1607                 :             :     }
    1608                 :             : 
    1609                 :             :     /*  1. Create initial ranks from equivalence information stored in nSymmRank */
    1610                 :           0 :     memcpy(pRankStack1[0], nSymmRank, num_at_tg * sizeof(pRankStack1[0][0]));
    1611                 :           0 :     pCG->m_pn_RankForSort = pRankStack1[0];
    1612                 :           0 :     tsort( pCG, pRankStack1[1], num_at_tg, sizeof( pRankStack1[1][0] ), CompRanksOrd );
    1613                 :           0 :     nNumDiffRanks = SortedEquInfoToRanks( pRankStack1[0]/*inp*/, pRankStack1[0]/*out*/, pRankStack1[1], num_at_tg, NULL );
    1614                 :             : 
    1615                 :             :     /* other neighbors */
    1616                 :           0 :     num_other_neigh = 0;
    1617   [ #  #  #  # ]:           0 :     if (at[ia].valence <= MAX_NUM_STEREO_ATOM_NEIGH && mode)
    1618                 :             :     {
    1619         [ #  # ]:           0 :         for (i = 0; i < at[ia].valence; i++)
    1620                 :             :         {
    1621   [ #  #  #  # ]:           0 :             if (i != in1 && i != in2)
    1622                 :             :             {
    1623                 :           0 :                 other_neigh[num_other_neigh] = (int) neigh_num[i];
    1624                 :           0 :                 other_neig_ord[num_other_neigh] = i;
    1625                 :           0 :                 num_other_neigh++;
    1626                 :             :             }
    1627                 :             :         }
    1628                 :             :     }
    1629   [ #  #  #  #  :           0 :     if ((mode != MAP_MODE_STD && nSymmRank[other_neigh[0]] != nSymmRank[other_neigh[1]]) ||
                   #  # ]
    1630         [ #  # ]:           0 :          (mode == MAP_MODE_S4 && nSymmRank[n1] != nSymmRank[other_neigh[1]])) /* djb-rwth: addressing LLVM warning */
    1631                 :             :     {
    1632                 :           0 :         return 0;
    1633                 :             :     }
    1634                 :             : 
    1635                 :             :     /*  2. Fix at[ia] */
    1636         [ #  # ]:           0 :     if (pRankStack1[0][ia] != nSymmRank[ia])
    1637                 :             :     {
    1638                 :             :         /*  at[ia] is constitutionally equivalent to some other atom. Fix at[ia]. */
    1639                 :           0 :         pRankStack1[0][ia] = nSymmRank[ia];
    1640                 :           0 :         nNumDiffRanks = DifferentiateRanksBasic( pCG, num_at_tg, NeighList,
    1641                 :             :                                      nNumDiffRanks, pRankStack1[0], nTempRank,
    1642                 :           0 :                                      pRankStack1[1], lNumIter, 1 );
    1643                 :             :     }
    1644                 :             :     /*  3. In case of a double bond/cumulene only: */
    1645                 :             :     /*     fix at[ib] -- the opposite double bond/cumulene atom */
    1646         [ #  # ]:           0 :     if (ib < num_atoms)
    1647                 :             :     {
    1648                 :             :         /*  find the smallest possible rank */
    1649                 :           0 :         nRank1 = pRankStack1[0][ib];
    1650                 :           0 :         nRank2 = GetMinNewRank( pRankStack1[0], pRankStack1[1], nRank1 );
    1651                 :             :         /*  if the rank is smaller than pRankStack1[0][ib] then fix at[ib] */
    1652         [ #  # ]:           0 :         if (nRank2 != nRank1)
    1653                 :             :         {
    1654                 :           0 :             pRankStack1[0][ib] = nRank2;
    1655                 :           0 :             nNumDiffRanks = DifferentiateRanksBasic( pCG, num_at_tg, NeighList,
    1656                 :             :                                          nNumDiffRanks, pRankStack1[0], nTempRank,
    1657                 :           0 :                                          pRankStack1[1], lNumIter, 1 );
    1658                 :             :         }
    1659                 :             :     }
    1660                 :             : 
    1661                 :             :     /**************************************************************************************
    1662                 :             :      * Note: It may (or may not?) make sense to fix "other neighbors":
    1663                 :             :      *       in case of a stereo center fix neighbors other than n1, n2
    1664                 :             :      *       in case of a double bond/cumulene fix the opposite atom neighbors
    1665                 :             :      *       The ranks assigned to the other neighbors in case of their equivalence
    1666                 :             :      *       should be in the ascending order of their canonical ranks ????
    1667                 :             :      *       *** For now we do not fix other neighbors ***
    1668                 :             :      **************************************************************************************/
    1669                 :             : 
    1670                 :             :     /*  4. Check whether the neighbors still have equal ranks */
    1671         [ #  # ]:           0 :     if (pRankStack1[0][n1] != pRankStack1[0][n2])
    1672                 :             :     {
    1673                 :           0 :         return 0; /*  the two neighbors are not constitutionally equivalent */
    1674                 :             :     }
    1675                 :             :     /*  5. Find new smallest possible rank for n1 and n2 */
    1676                 :           0 :     nRank1 = pRankStack1[0][n1];
    1677                 :           0 :     nRank2 = GetMinNewRank( pRankStack1[0], pRankStack1[1], nRank1 );
    1678                 :             : 
    1679                 :             :     /*  6. Copy the results to the 2nd eq. rank arrays */
    1680                 :           0 :     memcpy(pRankStack2[0], pRankStack1[0], num_at_tg * sizeof(pRankStack2[0][0]));
    1681                 :           0 :     memcpy(pRankStack2[1], pRankStack1[1], num_at_tg * sizeof(pRankStack2[0][0]));
    1682                 :             :     /*  7. Break neighbor tie: map n1(1) <--> n2(2) */
    1683                 :             :     /*  7. Break neighbor tie: map n1(1) <--> n2(2) */
    1684                 :           0 :     pRankStack1[0][n1] = nRank2;
    1685                 :           0 :     nNumDiffRanks1 = DifferentiateRanksBasic( pCG, num_at_tg, NeighList,
    1686                 :             :                                  nNumDiffRanks, pRankStack1[0], nTempRank,
    1687                 :           0 :                                  pRankStack1[1], lNumIter, 1 );
    1688                 :             : 
    1689                 :           0 :     pRankStack2[0][n2] = nRank2;
    1690                 :           0 :     nNumDiffRanks2 = DifferentiateRanksBasic( pCG, num_at_tg, NeighList,
    1691                 :             :                                  nNumDiffRanks, pRankStack2[0], nTempRank,
    1692                 :           0 :                                  pRankStack2[1], lNumIter, 1 );
    1693                 :             : 
    1694         [ #  # ]:           0 :     if (nNumDiffRanks1 != nNumDiffRanks2)
    1695                 :             :     {
    1696                 :           0 :         return -1; /*  <BRKPT> */
    1697                 :             :     }
    1698                 :             : 
    1699   [ #  #  #  # ]:           0 :     if (mode == MAP_MODE_C2v || mode == MAP_MODE_C2)
    1700                 :             :     {
    1701                 :             :         /* Check for C2v reflection leading to parity inversion (mode=1) or C2 rotation (mode=2) */
    1702                 :             :         AT_RANK nRank10, nRank20;
    1703                 :             :         int     nn1, nn2;
    1704                 :             :         /*
    1705                 :             :          * C2v & C2: map
    1706                 :             :          * n1(1) <--> n2(2) -- at this point already done
    1707                 :             :          * n1(2) <--> n2(1) --> do at i = 0
    1708                 :             :          *
    1709                 :             :          * C2v: other neighbors must be unmoved: map
    1710                 :             :          * other_neigh[0](1) <--> other_neigh[0](2)
    1711                 :             :          * other_neigh[1](1) <--> other_neigh[1](2)
    1712                 :             :          *
    1713                 :             :          * C2:  other neighbors should be mapped on each other
    1714                 :             :          * other_neigh[0](1) <--> other_neigh[1](2)
    1715                 :             :          * other_neigh[1](1) <--> other_neigh[0](2)
    1716                 :             :          */
    1717         [ #  # ]:           0 :         for (i = 0; i <= 2; i++)
    1718                 :             :         {
    1719         [ #  # ]:           0 :             if (i == 0)
    1720                 :             :             {
    1721                 :             :                 /* C2v & C2. Map n2(1) <--> n1(2) */
    1722                 :           0 :                 nn1 = n2;
    1723                 :           0 :                 nn2 = n1;
    1724                 :             :             }
    1725                 :             :             else
    1726                 :             :             {
    1727         [ #  # ]:           0 :                 if (mode == MAP_MODE_C2v)
    1728                 :             :                 {   /* was '=', pointed by WDI */
    1729                 :             :                     /* i = 1 or 2
    1730                 :             :                      * C2v. Other neighbors must be unmoved: map
    1731                 :             :                      * i=1: other_neigh[0](1) <--> other_neigh[0](2)
    1732                 :             :                      * i=2: other_neigh[1](1) <--> other_neigh[1](2)
    1733                 :             :                      */
    1734                 :           0 :                     nn1 = other_neigh[i - 1]; /* 0 or 1 */
    1735                 :           0 :                     nn2 = other_neigh[i - 1]; /* 0 or 1 */
    1736                 :             :                 }
    1737                 :             :                 else
    1738                 :             :                 {
    1739         [ #  # ]:           0 :                     if (mode == MAP_MODE_C2)
    1740                 :             :                     {
    1741                 :             :                         /* was '=', pointed by WDI */
    1742                 :             :                         /* i = 1 or 2
    1743                 :             :                          * C2.  Other neighbors should be mapped on each other
    1744                 :             :                          * i=1: other_neigh[0](1) <--> other_neigh[1](2)
    1745                 :             :                          * i=2: other_neigh[1](1) <--> other_neigh[0](2)
    1746                 :             :                          */
    1747                 :           0 :                         nn1 = other_neigh[i - 1]; /* 0 or 1 */
    1748                 :           0 :                         nn2 = other_neigh[2 - i]; /* 1 or 0 */
    1749                 :             :                     }
    1750                 :             :                     else
    1751                 :             :                     {
    1752                 :           0 :                         return -1; /* program error */
    1753                 :             :                     }
    1754                 :             :                 }
    1755                 :             :             }
    1756                 :             : 
    1757                 :             :             /* map nn1(1) <--> nn2(2) */
    1758                 :           0 :             nRank10 = pRankStack1[0][nn1];
    1759                 :           0 :             nRank20 = pRankStack2[0][nn2];
    1760                 :           0 :             nRank1 = GetMinNewRank( pRankStack1[0], pRankStack1[1], nRank10 );
    1761                 :           0 :             nRank2 = GetMinNewRank( pRankStack2[0], pRankStack2[1], nRank20 );
    1762   [ #  #  #  # ]:           0 :             if (nRank10 == nRank20 && nRank1 == nRank2)
    1763                 :             :             {
    1764         [ #  # ]:           0 :                 if (nRank10 == nRank1)
    1765                 :             :                 {
    1766                 :             :                     ; /* atoms are already mapped */
    1767                 :             :                 }
    1768                 :             :                 else
    1769                 :             :                 {
    1770                 :             :                     /* need additional mapping: ranks are not fixed yet */
    1771                 :           0 :                     pRankStack1[0][nn1] = nRank1;
    1772                 :           0 :                     nNumDiffRanks1 = DifferentiateRanksBasic( pCG, num_at_tg, NeighList,
    1773                 :             :                                                  nNumDiffRanks, pRankStack1[0], nTempRank,
    1774                 :           0 :                                                  pRankStack1[1], lNumIter, 1 );
    1775                 :           0 :                     pRankStack2[0][nn2] = nRank2;
    1776                 :           0 :                     nNumDiffRanks2 = DifferentiateRanksBasic( pCG, num_at_tg, NeighList,
    1777                 :             :                                                  nNumDiffRanks, pRankStack2[0], nTempRank,
    1778                 :           0 :                                                  pRankStack2[1], lNumIter, 1 );
    1779         [ #  # ]:           0 :                     if (nNumDiffRanks1 != nNumDiffRanks2)
    1780                 :             :                     {
    1781                 :           0 :                         return -1; /*  <BRKPT> */
    1782                 :             :                     }
    1783                 :             :                 }
    1784                 :             :             }
    1785                 :             :             else
    1786                 :             :             {
    1787                 :           0 :                 return 0;  /* mapping is not possible */
    1788                 :             :             }
    1789                 :             :         }
    1790                 :             :     }
    1791                 :             : 
    1792         [ #  # ]:           0 :     if (mode == MAP_MODE_S4)
    1793                 :             :     {
    1794                 :             :         /*
    1795                 :             :          *  Check for S4 reflection/rotation leading to parity inversion (mode=3)
    1796                 :             :          *
    1797                 :             :          * At this point n1(1) <--> n2(2) have been mapped and n1 has index in1 = 0
    1798                 :             :          * Below indexes in neigh_num[] are in brackets; [i] means neigh_num[i].
    1799                 :             :          * Numbers (#) in parentheses refer to pRankStack#
    1800                 :             :          *
    1801                 :             :          * in2=1: [0](1) <--> [1](2)  mapping has been done; add more mappings:
    1802                 :             :          *        [1](1) <--> [2](2)  [x]=[2]
    1803                 :             :          *        [2](1) <--> [3](2)  [y]=[3]
    1804                 :             :          *        [3](1) <--> [0](2)
    1805                 :             :          *        this will succeed if C2 axis crosses middle of [0]-[2] and [1]-[3] lines
    1806                 :             :          *
    1807                 :             :          * in2=2: [0](1) <--> [2](2) mapping has been done; add more mappings:
    1808                 :             :          *        [2](1) <--> [3](2)  [x]=[3]
    1809                 :             :          *        [3](1) <--> [1](2)  [y]=[1]
    1810                 :             :          *        [1](1) <--> [0](2)
    1811                 :             :          *        this will succeed if C2 axis crosses middle of [0]-[3] and [1]-[2] lines
    1812                 :             :          *
    1813                 :             :          * in2=3: [0](1) <--> [3](2) mapping has been done; add more mappings:
    1814                 :             :          *        [3](1) <--> [1](2)  [x]=[1]
    1815                 :             :          *        [1](1) <--> [2](2)  [y]=[2]
    1816                 :             :          *        [2](1) <--> [0](2)
    1817                 :             :          *        this will succeed if C2 axis crosses middle of [0]-[1] and [2]-[3] lines
    1818                 :             :          *
    1819                 :             :          * In general:
    1820                 :             :          *        [in1](1) <--> [in2](2)
    1821                 :             :          *        [in2](1) <--> [x]  (2)  i=0
    1822                 :             :          *        [x]  (1) <--> [y]  (2)  i=1
    1823                 :             :          *        [y]  (1) <--> [in1](2)  i=2
    1824                 :             :          *
    1825                 :             :          *    in1=0    always
    1826                 :             :          *    ===== how to find x, y from in2 ====
    1827                 :             :          *    in2=1 => x,y = 2, 3  or [x] = other_neigh[0], [y] = other_neigh[1]
    1828                 :             :          *    in2=2 => x,y = 3, 1  or [x] = other_neigh[1], [y] = other_neigh[0]
    1829                 :             :          *    in2=3 => x,y = 1, 2  or [x] = other_neigh[0], [y] = other_neigh[1]
    1830                 :             :          *    ====================================
    1831                 :             :          */
    1832                 :             :         AT_RANK nRank10, nRank20;
    1833                 :             :         int     nn1, nn2;
    1834         [ #  # ]:           0 :         for (i = 0; i <= 2; i++)
    1835                 :             :         {
    1836   [ #  #  #  # ]:           0 :             switch (i)
    1837                 :             :             {
    1838                 :           0 :                 case 0:  /* [in2](1) <--> [x](2);  */
    1839                 :           0 :                     nn1 = n2;                    /* [in2] */
    1840                 :           0 :                     nn2 = other_neigh[1 - in2 % 2];  /* [x]   */
    1841                 :           0 :                     break;
    1842                 :           0 :                 case 1:  /* [x](1) <--> [y](2) */
    1843                 :           0 :                     nn1 = other_neigh[1 - in2 % 2];  /* [x]   */
    1844                 :           0 :                     nn2 = other_neigh[in2 % 2];  /* [y]   */
    1845                 :           0 :                     break;
    1846                 :           0 :                 case 2:
    1847                 :           0 :                     nn1 = other_neigh[in2 % 2];  /* [y]   */
    1848                 :           0 :                     nn2 = n1;                    /* [in1] */
    1849                 :           0 :                     break;
    1850                 :           0 :                 default:
    1851                 :           0 :                     return -1; /* program error */
    1852                 :             :             }
    1853                 :             :             /* map nn1(1) <--> nn2(2) */
    1854                 :           0 :             nRank10 = pRankStack1[0][nn1];
    1855                 :           0 :             nRank20 = pRankStack2[0][nn2];
    1856                 :           0 :             nRank1 = GetMinNewRank( pRankStack1[0], pRankStack1[1], nRank10 );
    1857                 :           0 :             nRank2 = GetMinNewRank( pRankStack2[0], pRankStack2[1], nRank20 );
    1858   [ #  #  #  # ]:           0 :             if (nRank10 == nRank20 && nRank1 == nRank2)
    1859                 :             :             {
    1860         [ #  # ]:           0 :                 if (nRank10 == nRank1)
    1861                 :             :                 {
    1862                 :             :                     ;/* atoms are already mapped */
    1863                 :             :                 }
    1864                 :             :                 else
    1865                 :             :                 {
    1866                 :             :                              /* need additional mapping: ranks are not fixed yet */
    1867                 :           0 :                     pRankStack1[0][nn1] = nRank1;
    1868                 :           0 :                     nNumDiffRanks1 = DifferentiateRanksBasic( pCG, num_at_tg, NeighList,
    1869                 :             :                                                  nNumDiffRanks, pRankStack1[0], nTempRank,
    1870                 :           0 :                                                  pRankStack1[1], lNumIter, 1 );
    1871                 :           0 :                     pRankStack2[0][nn2] = nRank2;
    1872                 :           0 :                     nNumDiffRanks2 = DifferentiateRanksBasic( pCG, num_at_tg, NeighList,
    1873                 :             :                                                  nNumDiffRanks, pRankStack2[0], nTempRank,
    1874                 :           0 :                                                  pRankStack2[1], lNumIter, 1 );
    1875                 :             : 
    1876         [ #  # ]:           0 :                     if (nNumDiffRanks1 != nNumDiffRanks2)
    1877                 :             :                     {
    1878                 :           0 :                         return -1; /*  <BRKPT> */
    1879                 :             :                     }
    1880                 :             :                 }
    1881                 :             :             }
    1882                 :             :             else
    1883                 :             :             {
    1884                 :           0 :                 return 0;  /* mapping is not possible */
    1885                 :             :             }
    1886                 :             :         }
    1887                 :             :     }
    1888                 :             : 
    1889                 :             : #if ( BREAK_ONE_MORE_SC_TIE == 1 ) /* { */
    1890                 :             :     /* Check for a very highly symmetrical stereo center 12-06-2002 */
    1891   [ #  #  #  # ]:           0 :     if (ib >= num_atoms && at[ia].valence == MAX_NUM_STEREO_ATOM_NEIGH)
    1892                 :             :     {
    1893                 :             :         int num_eq;
    1894                 :           0 :         nRank1 = pRankStack1[0][n2];
    1895         [ #  # ]:           0 :         for (i = 0, num_eq = 0; i < at[ia].valence; i++)
    1896                 :             :         {
    1897                 :           0 :             num_eq += ( nRank1 == pRankStack1[0][at[ia].neighbor[i]] );
    1898                 :             :         }
    1899         [ #  # ]:           0 :         if (num_eq == MAX_NUM_STEREO_ATOM_NEIGH - 1)
    1900                 :             :         {
    1901   [ #  #  #  # ]:           0 :             for (i = (int) nRank1 - 1; 0 <= i && nRank1 == ( nRank2 = pRankStack1[0][(int) pRankStack1[1][i]] ); i--)
    1902                 :             :             {
    1903                 :             :                 ;
    1904                 :             :             }
    1905         [ #  # ]:           0 :             if (i >= 0)
    1906                 :             :             {
    1907                 :           0 :                 nRank2++;
    1908                 :             :             }
    1909                 :             :             else
    1910                 :             :             {
    1911                 :           0 :                 nRank2 = 1;
    1912                 :             :             }
    1913                 :             : 
    1914                 :             :             /*  7a. Break another neighbor tie */
    1915                 :           0 :             nNumDiffRanks = nNumDiffRanks1;
    1916                 :             : 
    1917                 :           0 :             pRankStack1[0][n2] = nRank2;
    1918                 :           0 :             nNumDiffRanks1 = DifferentiateRanksBasic( pCG, num_at_tg, NeighList,
    1919                 :             :                                          nNumDiffRanks, pRankStack1[0], nTempRank,
    1920                 :           0 :                                          pRankStack1[1], lNumIter, 1 );
    1921                 :             : 
    1922                 :           0 :             pRankStack2[0][n1] = nRank2;
    1923                 :           0 :             nNumDiffRanks2 = DifferentiateRanksBasic( pCG, num_at_tg, NeighList,
    1924                 :             :                                          nNumDiffRanks, pRankStack2[0], nTempRank,
    1925                 :           0 :                                          pRankStack2[1], lNumIter, 1 );
    1926                 :             :         }
    1927                 :             :     }
    1928                 :             : 
    1929         [ #  # ]:           0 :     if (nNumDiffRanks1 != nNumDiffRanks2)
    1930                 :             :     {
    1931                 :           0 :         return -1; /*  <BRKPT> */
    1932                 :             :     }
    1933                 :             : #endif /* } BREAK_ONE_MORE_SC_TIE */
    1934                 :             : 
    1935                 :             : #if ( BREAK_ALSO_NEIGH_TIE == 1 )
    1936                 :             :     /* check whether neighbor's neighbors are tied and untie them */
    1937                 :             :     if (at[n1].nRingSystem == at[n2].nRingSystem &&  ib >= num_atoms)
    1938                 :             :     {
    1939                 :             :         AT_RANK NeighNeighList[MAX_NUM_STEREO_ATOM_NEIGH + 1];
    1940                 :             :         int m, neigh1 = -1, neigh2 = -1;
    1941                 :             :         nRank1 = nRank2 = 0;
    1942                 :             :         /* n1 */
    1943                 :             :         NeighNeighList[0] = at[n1].valence - 1; /* for insertions_sort_NeighListBySymmAndCanonRank() */
    1944                 :             :         for (i = 0, m = 1; i < at[n1].valence; i++)
    1945                 :             :         {
    1946                 :             :             int neigh = at[n1].neighbor[i];
    1947                 :             :             if (neigh != ia)
    1948                 :             :             {
    1949                 :             :                 NeighNeighList[m++] = neigh;
    1950                 :             :             }
    1951                 :             :         }
    1952                 :             :         insertions_sort_NeighListBySymmAndCanonRank( NeighNeighList, pRankStack1[0], nCanonRank );
    1953                 :             :         for (m = 2; m < at[n1].valence; m++)
    1954                 :             :         {
    1955                 :             :             if (pRankStack1[0][NeighNeighList[m]] == pRankStack1[0][NeighNeighList[m - 1]])
    1956                 :             :             {
    1957                 :             :                 neigh1 = NeighNeighList[m - 1];
    1958                 :             :                 break;
    1959                 :             :             }
    1960                 :             :         }
    1961                 :             :         /* n2 */
    1962                 :             :         NeighNeighList[0] = at[n2].valence - 1; /* for insertions_sort_NeighListBySymmAndCanonRank() */
    1963                 :             :         for (i = 0, m = 1; i < at[n2].valence; i++)
    1964                 :             :         {
    1965                 :             :             int neigh = at[n2].neighbor[i];
    1966                 :             :             if (neigh != ia)
    1967                 :             :             {
    1968                 :             :                 NeighNeighList[m++] = neigh;
    1969                 :             :             }
    1970                 :             :         }
    1971                 :             :         insertions_sort_NeighListBySymmAndCanonRank( NeighNeighList, pRankStack2[0], nCanonRank );
    1972                 :             :         for (m = 2; m < at[n2].valence; m++)
    1973                 :             :         {
    1974                 :             :             if (pRankStack2[0][NeighNeighList[m]] == pRankStack2[0][NeighNeighList[m - 1]])
    1975                 :             :             {
    1976                 :             : #if ( BREAK_ALSO_NEIGH_TIE_ROTATE == 1 )
    1977                 :             :                 neigh2 = NeighNeighList[m];    /* [m] to obtain same axis orientation  around ia<neigh */
    1978                 :             : #else
    1979                 :             :                 neigh2 = NeighNeighList[m - 1];  /* [m-1] to obtain reflection ??? */
    1980                 :             : #endif
    1981                 :             :                 break;
    1982                 :             :             }
    1983                 :             :         }
    1984                 :             :         if (neigh1 >= 0 && neigh2 >= 0 && pRankStack1[0][neigh1] == pRankStack2[0][neigh2])
    1985                 :             :         {
    1986                 :             :             /* neighbors' neighbors are tied */
    1987                 :             :             nRank1 = pRankStack1[0][neigh1];
    1988                 :             :             nRank2 = GetMinNewRank( pRankStack1[0], pRankStack1[1], nRank1 );
    1989                 :             : 
    1990                 :             :             /*  Break neighbor's neighbor tie */
    1991                 :             : 
    1992                 :             :             nNumDiffRanks = nNumDiffRanks1;
    1993                 :             : 
    1994                 :             :             pRankStack1[0][neigh1] = nRank2;
    1995                 :             :             nNumDiffRanks1 = DifferentiateRanksBasic( pCG, num_at_tg, NeighList,
    1996                 :             :                                          nNumDiffRanks, pRankStack1[0], nTempRank,
    1997                 :             :                                          pRankStack1[1], lNumIter, 1 );
    1998                 :             : 
    1999                 :             :             pRankStack2[0][neigh2] = nRank2;
    2000                 :             :             nNumDiffRanks2 = DifferentiateRanksBasic( pCG, num_at_tg, NeighList,
    2001                 :             :                                          nNumDiffRanks, pRankStack2[0], nTempRank,
    2002                 :             :                                          pRankStack2[1], lNumIter, 1 );
    2003                 :             :         }
    2004                 :             :     }
    2005                 :             : #endif
    2006                 :             : 
    2007                 :             :     /*  for debug only */
    2008         [ #  # ]:           0 :     for (i = 0; i < num_at_tg; i++)
    2009                 :             :     {
    2010         [ #  # ]:           0 :         if (pRankStack1[0][(int) pRankStack1[1][i]] != pRankStack2[0][(int) pRankStack2[1][i]])
    2011                 :             :         {
    2012                 :           0 :             return -1;  /*  <BRKPT> */
    2013                 :             :         }
    2014                 :             :     }
    2015                 :             : 
    2016                 :             :     /*  Resort lists of  neighbors */
    2017                 :           0 :     SortNeighListsBySymmAndCanonRank( num_atoms, nl1, pRankStack1[0], nCanonRank );
    2018                 :           0 :     SortNeighListsBySymmAndCanonRank( num_atoms, nl2, pRankStack2[0], nCanonRank );
    2019                 :             : 
    2020                 :           0 :     return nNumDiffRanks1 + 1;
    2021                 :             : }
    2022                 :             : 
    2023                 :             : 
    2024                 :             : /****************************************************************************/
    2025                 :           0 : int CheckNextSymmNeighborsAndBonds( sp_ATOM *at,
    2026                 :             :                                     AT_RANK cur1,
    2027                 :             :                                     AT_RANK cur2,
    2028                 :             :                                     AT_RANK n1,
    2029                 :             :                                     AT_RANK n2,
    2030                 :             :                                     AT_RANK *nAvoidCheckAtom,
    2031                 :             :                                     AT_RANK *nVisited1,
    2032                 :             :                                     AT_RANK *nVisited2,
    2033                 :             :                                     AT_RANK *nVisitOrd1,
    2034                 :             :                                     AT_RANK *nVisitOrd2,
    2035                 :             :                                     const AT_RANK *nRank1,
    2036                 :             :                                     const AT_RANK *nRank2 )
    2037                 :             : {
    2038                 :           0 :     AT_RANK s1 = 0, s2 = 0;
    2039                 :             :     int     i1, i2, k1, k2;
    2040         [ #  # ]:           0 :     if (nRank1[n1] != nRank2[n2])
    2041                 :             :     {
    2042                 :           0 :         return -1; /*  parallel traversal in stereo removal failed */ /*   <BRKPT> */
    2043                 :             :     }
    2044      [ #  #  # ]:           0 :     switch (!nVisited1[n1] + !nVisited2[n2])
    2045                 :             :     {
    2046                 :           0 :         case 0:
    2047   [ #  #  #  # ]:           0 :             if (nVisited1[n1] != n2 + 1 || nVisited2[n2] != n1 + 1)
    2048                 :             :             {
    2049                 :           0 :                 return -1; /*  0; */ /*  possibly error???: we have come to an alreardy traversed pair and */
    2050                 :             :                            /*  found that the pair previously has not been traversed synchroneously. */
    2051                 :             :             }              /*  -- Happens in C60. */
    2052                 :           0 :             break;
    2053                 :           0 :         case 1:
    2054                 :           0 :             return -1; /*  0; */ /*  possibly error: one is zero, another is not a zero. Happens in C60 */
    2055                 :             : 
    2056                 :             :         /*  case 2: */
    2057                 :             :             /* both are zero, OK. */
    2058                 :             :     }
    2059                 :             : 
    2060         [ #  # ]:           0 :     if (nVisitOrd1[n1] != nVisitOrd2[n2])
    2061                 :             :     {
    2062                 :           0 :         return -1; /*  0; */ /*  different DFS trees */
    2063                 :             :     }
    2064                 :             :     /*  at[n1] and at[n2] are next to at[cur1] and at[cur2] respectively */
    2065                 :             :     /*  Even though the bond might have already been checked, check whether */
    2066                 :             :     /*  it is a stereo bond/cumulene. If it is, check the bond/cumulene parity. */
    2067                 :             : 
    2068                 :             :     /*  Even though the bond or cumulene might have already been checked, check it: this is */
    2069                 :             :     /*  the only place we can check stereo bonds and cumulenes that are not edges of the DFS tree */
    2070                 :             :     /*  The code works both for a stereo bond and a stereogenic cumulene. */
    2071                 :             : 
    2072                 :           0 :     for (i1 = 0, k1 = 0; i1 < MAX_NUM_STEREO_BONDS &&
    2073   [ #  #  #  # ]:           0 :         ( s1 = at[cur1].stereo_bond_neighbor[i1] ) &&
    2074         [ #  # ]:           0 :                          !( k1 = ( at[cur1].neighbor[(int) at[cur1].stereo_bond_ord[i1]] == n1 ) ); i1++)
    2075                 :             :     {
    2076                 :             :         ;
    2077                 :             :     }
    2078                 :           0 :     for (i2 = 0, k2 = 0; i2 < MAX_NUM_STEREO_BONDS &&
    2079   [ #  #  #  # ]:           0 :         ( s2 = at[cur2].stereo_bond_neighbor[i2] ) &&
    2080         [ #  # ]:           0 :                          !( k2 = ( at[cur2].neighbor[(int) at[cur2].stereo_bond_ord[i2]] == n2 ) ); i2++)
    2081                 :             :     {
    2082                 :             :         ;
    2083                 :             :     }
    2084                 :             : 
    2085                 :             :     /* -- this does not work in case of cumulenes --
    2086                 :             :     for ( i1 = 0, k1 = 0; i1 < MAX_NUM_STEREO_BONDS && (s1=at[cur1].stereo_bond_neighbor[i1]) && !(k1=(s1-1 == n1)); i1 ++ )
    2087                 :             :         ;
    2088                 :             :     for ( i2 = 0, k2 = 0; i2 < MAX_NUM_STEREO_BONDS && (s2=at[cur2].stereo_bond_neighbor[i2]) && !(k2=(s2-1 == n2)); i2 ++ )
    2089                 :             :         ;
    2090                 :             :     */
    2091                 :             : 
    2092         [ #  # ]:           0 :     if (k1 != k2)
    2093                 :             :     {
    2094                 :           0 :         return 0; /*  not an error: a stereo bond and not a stereo bond */
    2095                 :             :     }
    2096         [ #  # ]:           0 :     if (k1)
    2097                 :             :     {
    2098                 :             :         /* here k1 == k2 */
    2099                 :             :         int bCheckBond1, bCheckBond2;
    2100                 :           0 :         s1--;
    2101                 :           0 :         s2--;
    2102                 :             : 
    2103   [ #  #  #  # ]:           0 :         bCheckBond1 = ( cur1 != nAvoidCheckAtom[0] || s1 != nAvoidCheckAtom[1] ) &&
    2104   [ #  #  #  # ]:           0 :             ( cur1 != nAvoidCheckAtom[1] || s1 != nAvoidCheckAtom[0] );
    2105   [ #  #  #  # ]:           0 :         bCheckBond2 = ( cur2 != nAvoidCheckAtom[0] || s2 != nAvoidCheckAtom[1] ) &&
    2106   [ #  #  #  # ]:           0 :             ( cur2 != nAvoidCheckAtom[1] || s2 != nAvoidCheckAtom[0] );
    2107                 :             : 
    2108         [ #  # ]:           0 :         if (bCheckBond1 != bCheckBond2)
    2109                 :           0 :             return 0;
    2110                 :             : 
    2111   [ #  #  #  # ]:           0 :         if (!bCheckBond1 && !bCheckBond2)
    2112                 :             :         {
    2113                 :           0 :             return 1; /*  do not go any further in this direction */
    2114                 :             :         }
    2115                 :             : 
    2116         [ #  # ]:           0 :         if (at[cur1].stereo_bond_parity[i1] != at[cur2].stereo_bond_parity[i2])
    2117                 :             :         {
    2118                 :             :             /*  different values of  at[].stereo_bond_parity: definitely different bonds */
    2119                 :             :             /*  known parities */
    2120   [ #  #  #  # ]:           0 :             if (PARITY_KNOWN( at[cur1].stereo_bond_parity[i1] ) &&
    2121   [ #  #  #  # ]:           0 :                  PARITY_KNOWN( at[cur2].stereo_bond_parity[i2] ))
    2122                 :             :             {
    2123                 :           0 :                 return 0; /*  different currently known stereo bond parities */
    2124                 :             :             }
    2125                 :             : #if ( PROPAGATE_ILL_DEF_STEREO != 1 )
    2126                 :             :             /*  well defined and to be calculated from the ranks */
    2127                 :             :             if (!( PARITY_CALCULATE( at[cur1].stereo_bond_parity[i1] ) && PARITY_WELL_DEF( at[cur2].stereo_bond_parity[i2] ) ||
    2128                 :             :                 PARITY_WELL_DEF( at[cur1].stereo_bond_parity[i1] ) && PARITY_CALCULATE( at[cur2].stereo_bond_parity[i2] ) ||
    2129                 :             :                 PARITY_CALCULATE( at[cur1].stereo_bond_parity[i1] ) && PARITY_CALCULATE( at[cur2].stereo_bond_parity[i2] ) ))
    2130                 :             :             {
    2131                 :             : /*  do not reject if: "well defined" and "calculate" or "calculate" and "calculate" */
    2132                 :             :                 return 0;
    2133                 :             :             }
    2134                 :             : #endif
    2135                 :             :         }
    2136                 :             : 
    2137                 :             : #if ( PROPAGATE_ILL_DEF_STEREO != 1 )
    2138                 :             :         if (( cur1 != cur2 || s1 != s2 ) && ( cur1 != s2 || cur2 != s1 ))
    2139                 :             :         {
    2140                 :             : /*  two different stereo bonds */
    2141                 :             :             if (PARITY_ILL_DEF( at[cur1].stereo_bond_parity[i1] ) ||
    2142                 :             :                  PARITY_ILL_DEF( at[cur2].stereo_bond_parity[i2] ))
    2143                 :             :             {
    2144                 :             :                 return 0;
    2145                 :             :             }
    2146                 :             :         }
    2147                 :             : #endif
    2148                 :             :     }
    2149                 :             : 
    2150                 :           0 :     return 1; /*  stereo bonds to n1 and n2 have same known parities or are not stereo bonds */
    2151                 :             : }
    2152                 :             : 
    2153                 :             : 
    2154                 :             : /****************************************************************************/
    2155                 :             : 
    2156                 :           0 : int CreateCheckSymmPaths( sp_ATOM *at,
    2157                 :             :                           AT_RANK prev1,
    2158                 :             :                           AT_RANK cur1,
    2159                 :             :                           AT_RANK prev2,
    2160                 :             :                           AT_RANK cur2,
    2161                 :             :                           AT_RANK *nAvoidCheckAtom,
    2162                 :             :                           AT_RANK *nVisited1,
    2163                 :             :                           AT_RANK *nVisited2,
    2164                 :             :                           AT_RANK *nVisitOrd1,
    2165                 :             :                           AT_RANK *nVisitOrd2,
    2166                 :             :                           NEIGH_LIST *nl1,
    2167                 :             :                           NEIGH_LIST *nl2,
    2168                 :             :                           const AT_RANK *nRank1,
    2169                 :             :                           const AT_RANK *nRank2,
    2170                 :             :                           AT_RANK *nCanonRank,
    2171                 :             :                           AT_RANK *nLength,
    2172                 :             :                           int *bParitiesInverted,
    2173                 :             :                           int mode )
    2174                 :             : {
    2175                 :           0 :     int k, k1, k2, ret = 0, bParitiesInvertedZero = 0, *pbParitiesInverted;
    2176                 :             :     AT_RANK n1, n2;
    2177                 :             : 
    2178                 :           0 :     nVisited1[cur1] = cur2 + 1;  /*  symmetrically exchange atom numbers */
    2179                 :           0 :     nVisited2[cur2] = cur1 + 1;
    2180                 :             : 
    2181                 :           0 :     ( *nLength )++;
    2182                 :             : 
    2183                 :           0 :     nVisitOrd1[cur1] = *nLength; /*  save DFS visit order */
    2184                 :           0 :     nVisitOrd2[cur2] = *nLength;
    2185                 :             : 
    2186                 :             :     /* new version allows all inverted parities */
    2187   [ #  #  #  # ]:           0 :     if (PARITY_WELL_DEF( at[cur1].stereo_atom_parity ) &&
    2188   [ #  #  #  # ]:           0 :          PARITY_WELL_DEF( at[cur2].stereo_atom_parity ))
    2189                 :             :     {
    2190         [ #  # ]:           0 :         if (*bParitiesInverted < 0)
    2191                 :             :         {
    2192                 :           0 :             *bParitiesInverted = ( at[cur1].stereo_atom_parity + at[cur2].stereo_atom_parity ) % 2;
    2193                 :             :         }
    2194                 :             :         else
    2195                 :             :         {
    2196         [ #  # ]:           0 :             if (*bParitiesInverted != ( at[cur1].stereo_atom_parity + at[cur2].stereo_atom_parity ) % 2)
    2197                 :             :             {
    2198                 :           0 :                 return 0; /*  Different known in advance parities have wrong "inverted" relation */
    2199                 :             :             }
    2200                 :             :         }
    2201                 :             :     }
    2202                 :             :     else
    2203                 :             :     {
    2204   [ #  #  #  # ]:           0 :         if (PARITY_KNOWN( at[cur1].stereo_atom_parity ) &&
    2205   [ #  #  #  # ]:           0 :             PARITY_KNOWN( at[cur2].stereo_atom_parity ) &&
    2206         [ #  # ]:           0 :             at[cur1].stereo_atom_parity != at[cur2].stereo_atom_parity)
    2207                 :             :         {
    2208                 :           0 :             return 0;  /*  Different known in advance parities */
    2209                 :             :         }
    2210                 :             :     }
    2211                 :             : 
    2212         [ #  # ]:           0 :     if (cur1 != cur2 &&
    2213   [ #  #  #  # ]:           0 :          !at[cur1].stereo_bond_neighbor[0] && !at[cur2].stereo_bond_neighbor[0] &&
    2214   [ #  #  #  #  :           0 :          PARITY_KNOWN( at[cur1].parity ) != PARITY_KNOWN( at[cur2].parity ))
          #  #  #  #  #  
                      # ]
    2215                 :             :     {
    2216                 :           0 :         return 0; /*  one atom is stereogenic, another (presumably equivalent) is not. 9-11-2002 */
    2217                 :             :     }
    2218                 :             : #if ( PROPAGATE_ILL_DEF_STEREO != 1 )
    2219                 :             :     if (cur1 != cur2 &&
    2220                 :             :         ( PARITY_ILL_DEF( at[cur1].stereo_atom_parity ) ||
    2221                 :             :             PARITY_ILL_DEF( at[cur2].stereo_atom_parity ) )
    2222                 :             :        )
    2223                 :             :     {
    2224                 :             :         return 0;  /*  Cannot detect whether the paths are same or different */
    2225                 :             :     }
    2226                 :             : #endif
    2227                 :             : 
    2228         [ #  # ]:           0 :     if (at[cur1].valence != at[cur2].valence)
    2229                 :             :     {
    2230                 :           0 :         return CT_REMOVE_STEREO_ERR; /*  program error */ /*   <BRKPT> */
    2231                 :             :     }
    2232         [ #  # ]:           0 :     if (at[cur1].valence == 1)
    2233                 :             :     {
    2234                 :           0 :         return 1; /*  so far success */
    2235                 :             :     }
    2236                 :             : 
    2237   [ #  #  #  # ]:           0 :     if (nl1[(int) cur1][0] != nl2[(int) cur2][0] || nl1[(int) cur1][0] != at[cur1].valence)
    2238                 :             :     {
    2239                 :           0 :         return CT_REMOVE_STEREO_ERR; /*  error: different valences */ /*   <BRKPT> */
    2240                 :             :     }
    2241                 :             : 
    2242                 :             : 
    2243         [ #  # ]:           0 :     for (k = 1, k1 = 1, k2 = 1; k < at[cur1].valence; k++, k1++, k2++)
    2244                 :             :     {
    2245         [ #  # ]:           0 :         if (( n1 = nl1[(int) cur1][k1] ) == prev1)
    2246                 :             :         {
    2247                 :           0 :             n1 = nl1[(int) cur1][++k1]; /*  don't go back */
    2248                 :             :         }
    2249         [ #  # ]:           0 :         if (( n2 = nl2[(int) cur2][k2] ) == prev2)
    2250                 :             :         {
    2251                 :           0 :             n2 = nl2[(int) cur2][++k2]; /*  don't go back */
    2252                 :             :         }
    2253                 :             : 
    2254         [ #  # ]:           0 :         if (0 >= ( ret = CheckNextSymmNeighborsAndBonds( at, cur1, cur2, n1, n2, nAvoidCheckAtom,
    2255                 :             :             nVisited1, nVisited2, nVisitOrd1, nVisitOrd2, nRank1, nRank2 ) ))
    2256                 :             :         {
    2257                 :           0 :             return ret; /*  different neighbors or bonds                       */
    2258                 :             :         }
    2259                 :             : 
    2260         [ #  # ]:           0 :         if (!nVisited1[n1])
    2261                 :             :         {
    2262                 :             :             /*  recursion */
    2263                 :             :             /* allow all inverted parities only inside a single ring system containing the starting point */
    2264         [ #  # ]:           0 :             pbParitiesInverted = ( at[cur1].nRingSystem == at[n1].nRingSystem ) ? bParitiesInverted : &bParitiesInvertedZero;
    2265         [ #  # ]:           0 :             if (0 >= ( ret = CreateCheckSymmPaths( at, cur1, n1, cur2, n2, nAvoidCheckAtom,
    2266                 :             :                 nVisited1, nVisited2, nVisitOrd1, nVisitOrd2,
    2267                 :             :                 nl1, nl2, nRank1, nRank2, nCanonRank, nLength, pbParitiesInverted, mode ) ))
    2268                 :             :             {
    2269                 :           0 :                 return ret;
    2270                 :             :             }
    2271                 :             :         }
    2272                 :             :     }
    2273                 :             : 
    2274                 :           0 :     return 1; /*  Success */
    2275                 :             : }
    2276                 :             : 
    2277                 :             : 
    2278                 :             : /**************************************************************************************/
    2279                 :             : /*  Compare parities */
    2280                 :             : #define MAX_OTHER_NEIGH        2
    2281                 :             : /*  nNeighMode */
    2282                 :             : #define NEIGH_MODE_RING        1
    2283                 :             : #define NEIGH_MODE_CHAIN       2
    2284                 :             : 
    2285                 :             : #define CHECKING_STEREOCENTER  1
    2286                 :             : #define CHECKING_STEREOBOND    2
    2287                 :             : 
    2288                 :             : #define COMP_STEREO_SUCCESS    1
    2289                 :             : #define NOT_WELL_DEF_UNKN      2
    2290                 :             : #define NOT_WELL_DEF_UNDF      4
    2291                 :             : 
    2292                 :             : #define PARITY_IMPOSSIBLE    999
    2293                 :             : /**************************************************************************************
    2294                 :             :   Note:    the following C2v/S4 stereo center symmetry recognition
    2295                 :             :            is not included in the final InChI version released in April 2005
    2296                 :             :            It is disabled in the mode.h (CHECK_C2v_S4_SYMM = 0)
    2297                 :             :            As the result, the only central atom in S4 or atoms on C2v axis
    2298                 :             :            may have pasrity (-) even though these atoms are not stereogenic.
    2299                 :             : 
    2300                 :             :   Reason:  Not finished/tested yet
    2301                 :             :  **************************************************************************************
    2302                 :             : 
    2303                 :             :   In case of stereocenter with 2 pairs of constitutionally identical neighbors :
    2304                 :             : 
    2305                 :             :   G(n) > H(m) means group G has n elements; group H has m elements and
    2306                 :             :                                             group H is a subgroup of G
    2307                 :             : 
    2308                 :             :   Td(24) > D2d(8> > D2(4)
    2309                 :             :                   > S4(4)  > C2(2) -- Test for S4
    2310                 :             :                   > C2v(4) > C2(2) -- Test for C2v
    2311                 :             :                            > Cs(2)
    2312                 :             : 
    2313                 :             :   Td(24) > C3v(6) > C3(3) -- does not have 2 pairs of constitutionally identical neighbors
    2314                 :             :                   > Cs(2)
    2315                 :             : 
    2316                 :             :   The pair of atoms to check for the existence of a steregenic atom: X, Y
    2317                 :             : 
    2318                 :             :        X   Y
    2319                 :             :         \ /
    2320                 :             :          C
    2321                 :             :         / \
    2322                 :             :        A   B
    2323                 :             : 
    2324                 :             :   Conditions to check:
    2325                 :             : 
    2326                 :             :   (a) Old #0: Map canonical numbers X1 <--> Y2
    2327                 :             :       Traverse DFS from X and Y
    2328                 :             :       If all parities vs. canon. numbers unchanged except that of C
    2329                 :             :       then C is not stereogenic
    2330                 :             : 
    2331                 :             :   (b) C2v  #1: discover ACB symmetry plain Cv
    2332                 :             :       o Map canonical numbers X1 <--> Y2, Fix(Ai), Fix(Bi)
    2333                 :             :       o Make sure that after mapping X1 <--> Y2 the atoms Ai and
    2334                 :             :         Bi still have equal mapping ranks
    2335                 :             :       Traverse DFS from X and Y
    2336                 :             :       In this case canonical numbers will be reflected in plane ACB if it exists.
    2337                 :             :       o Criterion of the presence of the symmetry plain is:
    2338                 :             :         --> all stereogenic atoms and allenes parities are inverted
    2339                 :             :   (c) C2v  #2: discover vertical axis C2
    2340                 :             :       o Map canonical numbers X1 <--> Y2 and A1 <--> B2
    2341                 :             :       o Make sure that after mapping X1 <--> Y2 the atoms Ai and
    2342                 :             :         Bi still have equal mapping ranks
    2343                 :             :       o Traverse DFS from X1 and Y2
    2344                 :             :         In this case canonical numbers will be rotated by
    2345                 :             :                      180 degrees around the vertical axis
    2346                 :             :          (this may be considered as a superposition of two Cv
    2347                 :             :           reflections in perpendicular vertical planes)
    2348                 :             :       o Criterion of the presence of the C2 axis is:
    2349                 :             :         --> all stereogenic atoms and allenes parities are not changed
    2350                 :             :   (d) S4  #3: discover axis horizontal S4 axis
    2351                 :             :       o Map canonical numbers X1 <--> Y2, Y1 <--> A2, A1 <--> B2, B1 <--> X2
    2352                 :             :       o Traverse DFS from X1 and Y2
    2353                 :             :         In this case the canonical numbers will be rotated by
    2354                 :             :                      90 degrees and reflected in a horizontal plane.
    2355                 :             :         3 attempts corrresponding to transpositions 0132, 0213, 0321
    2356                 :             :                                  are sufficient (XY=01,02,03)
    2357                 :             :       o Criterion of the presence of the S4 symmetry axis is:
    2358                 :             :         --> all stereogenic atoms and allenes parities are inverted
    2359                 :             : 
    2360                 :             : ***************************************************************************************/
    2361                 :             : 
    2362                 :             : 
    2363                 :             : /****************************************************************************/
    2364                 :           0 : int CalculatedPathsParitiesAreIdentical( CANON_GLOBALS *pCG,
    2365                 :             :                                          sp_ATOM *at, int num_atoms,
    2366                 :             :                                          const AT_RANK *nSymmRank,
    2367                 :             :                                          AT_RANK *nCanonRank,
    2368                 :             :                                          AT_RANK *nAtomNumberCanon,
    2369                 :             :                                          AT_RANK *nAtomNumberCanon1,
    2370                 :             :                                          AT_RANK *nAtomNumberCanon2,
    2371                 :             :                                          AT_RANK *nVisited1,
    2372                 :             :                                          AT_RANK *nVisited2,
    2373                 :             :                                          AT_RANK prev_sb_neigh,
    2374                 :             :                                          AT_RANK cur,
    2375                 :             :                                          AT_RANK next1,
    2376                 :             :                                          AT_RANK next2,
    2377                 :             :                                          int nNeighMode,
    2378                 :             :                                          int bParitiesInverted,
    2379                 :             :                                          int mode,
    2380                 :             :                                          CANON_STAT *pCS,
    2381                 :             :                                          int vABParityUnknown )
    2382                 :             : {
    2383                 :             :     int i, i01, i02, i11, i12, i21, i22, k, parity, parity1, parity2, parity12, num_other_neigh;
    2384                 :             :     int nNumEqStereogenic, nCheckingMode, not_well_def_parities;
    2385                 :             :     AT_RANK other_neigh[MAX_NUM_STEREO_ATOM_NEIGH], neigh, r1, r2;
    2386                 :           0 :     int  nNumComparedCenters = 0, nNumComparedBonds = 0, bCurParityInv1 = 0 /*, bCurParityInv2=0*/;
    2387                 :           0 :     int  bCurRotated = 0, nNumDiff = 0, nNumInv = 0;
    2388                 :             :     int  s1, s2;
    2389                 :             : 
    2390         [ #  # ]:           0 :     nCheckingMode = ( prev_sb_neigh < num_atoms ) ? CHECKING_STEREOBOND : CHECKING_STEREOCENTER;
    2391                 :           0 :     not_well_def_parities = 0;
    2392                 :           0 :     nNumEqStereogenic = 0;
    2393                 :             : 
    2394   [ #  #  #  # ]:           0 :     if ((nNeighMode != NEIGH_MODE_RING &&
    2395         [ #  # ]:           0 :          bParitiesInverted != 0) || abs( bParitiesInverted ) != 1) /* djb-rwth: addressing LLVM warning */
    2396                 :             :     {
    2397                 :           0 :         bParitiesInverted = 0;
    2398                 :             :     }
    2399                 :             : 
    2400         [ #  # ]:           0 :     if (bParitiesInverted)
    2401                 :             :     {
    2402         [ #  # ]:           0 :         for (i = 0, i11 = i22 = 0; i < num_atoms; i++)
    2403                 :             :         {
    2404                 :             :             /* count number of atoms that have not been visited */
    2405                 :           0 :             i11 += !nVisited1[i];
    2406                 :           0 :             i22 += !nVisited2[i];
    2407                 :           0 :             nAtomNumberCanon1[i] = MAX_ATOMS + 1;  /*  mark unchanged */
    2408                 :           0 :             nAtomNumberCanon2[i] = MAX_ATOMS + 1;  /*  mark unchanged */
    2409                 :             :         }
    2410   [ #  #  #  # ]:           0 :         if (i11 || i22)
    2411                 :             :         {
    2412         [ #  # ]:           0 :             if (bParitiesInverted == 1)
    2413                 :             :             {
    2414                 :           0 :                 return 0; /* only a part of the structure has been inverted */
    2415                 :             :             }
    2416                 :             :             else
    2417                 :             :             {
    2418                 :           0 :                 bParitiesInverted = 0;
    2419                 :             :             }
    2420                 :             :         }
    2421                 :             :     }
    2422                 :             :     else
    2423                 :             :     {
    2424         [ #  # ]:           0 :         for (i = 0; i < num_atoms; i++)
    2425                 :             :         {
    2426                 :           0 :             nAtomNumberCanon1[i] = MAX_ATOMS + 1;  /*  mark unchanged */
    2427                 :           0 :             nAtomNumberCanon2[i] = MAX_ATOMS + 1;  /*  mark unchanged */
    2428                 :             :         }
    2429                 :             :     }
    2430   [ #  #  #  #  :           0 :     if ((bParitiesInverted > 0 && !( mode == MAP_MODE_C2v || mode == MAP_MODE_S4 )) ||
             #  #  #  # ]
    2431   [ #  #  #  # ]:           0 :          (bParitiesInverted == 0 && !( mode == MAP_MODE_C2 || mode == MAP_MODE_STD ))) /* djb-rwth: addressing LLVM warning */
    2432                 :             :     {
    2433                 :           0 :         return 0;
    2434                 :             :     }
    2435                 :             :     /**************************************************************************************
    2436                 :             :      *    The following discussion assumes that the canonical numbers are
    2437                 :             :      *    switched for some pairs of constitutionally identical atoms
    2438                 :             :      *    in such a way that the new numbering is an equivalent to the
    2439                 :             :      *    nCanonRank[] canonical numbering (the transposition belongs to the
    2440                 :             :      *    automorphism group of the chemical structure having no stereo).
    2441                 :             :      *    At this point non-zero elements of nVisited1[] and nVisited2[]
    2442                 :             :      *    together contain transposition P of the atom numbers.
    2443                 :             :      *    and P2 respectively of the ordering atom numbers: nVisitedi[k] = Pi(k)+1;
    2444                 :             :      *    In this implementation:
    2445                 :             :      *       P1(k)=k for all k
    2446                 :             :      *       P2(cur)=cur, P2(next1)=next2, P2(next2)=next1
    2447                 :             :      *
    2448                 :             :      *    Below we call one of the numberings "old", another "new".
    2449                 :             :      *
    2450                 :             :      *    *IF* the old and the new canonical numberings produce same parities for stereogenic
    2451                 :             :      *    elements for the same canonical number(s)
    2452                 :             :      *    (that is, old_parity(canon_number) == new_parity(canon_number)
    2453                 :             :      *    *except* the currently being tested stereocenter at[cur] or stereobond/cumulene
    2454                 :             :      *    at[cur]=at[prev_sb_neigh], whose parity MUST be inverted
    2455                 :             :      *
    2456                 :             :      *    *THEN* the stereocenter or stereobond/cumulene is not stereogenic with one
    2457                 :             :      *
    2458                 :             :      *    *EXCEPTION* If the currently tested stereogenic element is constitutionally
    2459                 :             :      *    equivalent to two or more other stereogenic elements that have been
    2460                 :             :      *    permuted then the currently tested one is still stereogenic.
    2461                 :             :      **************************************************************************************/
    2462                 :             : 
    2463                 :             :      /*
    2464                 :             :      * 1. replace the assigned in each of the parallel traversals atom numbers
    2465                 :             :      *    with the canon. ranks corresponding to the atom numbers in the
    2466                 :             :      *    currently numbered atoms at[].
    2467                 :             :      *    One of obtained this way canonical numberings (probably nVisited1[])
    2468                 :             :      *    is same as the nCanonRank[] because usually nVisited1[i] = i+1 or 0
    2469                 :             :      */
    2470         [ #  # ]:           0 :     for (i = 0; i < num_atoms; i++)
    2471                 :             :     {
    2472         [ #  # ]:           0 :         if (nVisited1[i])
    2473                 :             :         {
    2474                 :             :             /* canonical number of the atom mapped on atom #i in 'left' path */
    2475                 :           0 :             nVisited1[i] = nCanonRank[(int) nVisited1[i] - 1];
    2476                 :             :             /* reverse: atom # from the mapped canonical rank in 'left' path */
    2477                 :           0 :             nAtomNumberCanon1[nVisited1[i] - 1] = i;
    2478                 :             :         }
    2479         [ #  # ]:           0 :         if (nVisited2[i])
    2480                 :             :         {
    2481                 :             :             /* canonical number of the atom mapped on atom #i in 'right' path */
    2482                 :           0 :             nVisited2[i] = nCanonRank[(int) nVisited2[i] - 1];
    2483                 :             :             /* reverse: atom # from the mapped canonical rank in 'right' path */
    2484                 :           0 :             nAtomNumberCanon2[nVisited2[i] - 1] = i;
    2485                 :             :         }
    2486                 :             :         /* if 'left' and 'right' path do not have atoms in common except the
    2487                 :             :            starting atom (and in case of stereobond, the end atom) some of
    2488                 :             :            nVisitedi[i] elements may be zero.
    2489                 :             :         */
    2490                 :             :     }
    2491                 :             : 
    2492                 :             :     /*
    2493                 :             :      * if started with a stereobond then check whether its parity has changed.
    2494                 :             :      * If yes then continue, otherwise parities are different
    2495                 :             :      *
    2496                 :             :      * if started with a stereo center then prev_sb_neigh = MAX_ATOMS+1
    2497                 :             :      *
    2498                 :             :      * If the transposition of next1 and next2 changes only the parity of the starting stereo atom or stereo bond
    2499                 :             :      * then the stereo bond or stereo atom is not stereogenic
    2500                 :             :      *
    2501                 :             :      * The exception: the stereogenic elememt in question is equivalent
    2502                 :             :      *    to two or more traversed other stereogenic elememts
    2503                 :             :      *    (see nNumEqStereogenic below, case similar to trimethylcyclopropane:
    2504                 :             :      *     3 or more constitutionally equivalent stereogenic elements)
    2505                 :             :      */
    2506         [ #  # ]:           0 :     if (nCheckingMode == CHECKING_STEREOBOND)
    2507                 :             :     {
    2508                 :             :         /******************************************************************************
    2509                 :             :          *
    2510                 :             :          *  Possibly stereogenic starting bond or cumulene at[cur]-at[prev_sb_neigh]
    2511                 :             :          *
    2512                 :             :          *******************************************************************************/
    2513                 :             :         /*  checking the starting stereo bond */
    2514   [ #  #  #  # ]:           0 :         if (nVisited1[prev_sb_neigh] || nVisited2[prev_sb_neigh])
    2515                 :             :         {
    2516                 :             :             /*  the bond or cumulene is in the ring and the opposite atom has been visited */
    2517         [ #  # ]:           0 :             if (nVisited1[prev_sb_neigh] != nVisited2[prev_sb_neigh] ||
    2518         [ #  # ]:           0 :                  nCanonRank[prev_sb_neigh] != nVisited2[prev_sb_neigh])
    2519                 :             :             {
    2520                 :           0 :                 return 0; /*  error: we came back to the same bond/cumulene and */ /*   <BRKPT> */
    2521                 :             :                           /*  assigned different canon. ranks to the opposite atom. */
    2522                 :             :             }
    2523         [ #  # ]:           0 :             if (at[prev_sb_neigh].valence + at[prev_sb_neigh].num_H > 3)
    2524                 :             :             {
    2525                 :           0 :                 return 0;   /*  at[prev_sb_neigh] atom can not be adjacent to a stereo bond/cumulene */
    2526                 :             :                             /*  or does not have 3 attachments (hydrogens are not considered here) */
    2527                 :             :             }
    2528                 :           0 :             for (i = 0, k = 0; i < MAX_NUM_STEREO_BONDS &&
    2529   [ #  #  #  #  :           0 :                 ( neigh = at[prev_sb_neigh].stereo_bond_neighbor[i] ) && !( k = ( neigh - 1 == cur ) );
                   #  # ]
    2530                 :           0 :                 i++)
    2531                 :             :             {
    2532                 :             :                 ;
    2533                 :             :             }
    2534         [ #  # ]:           0 :             if (!k)
    2535                 :             :             {
    2536                 :           0 :                 return -1; /*  program error: could not locate stereogenic bond mark on the opposite atom */
    2537                 :             :             }
    2538                 :           0 :             k = (int) at[prev_sb_neigh].stereo_bond_ord[i]; /*  seq. number of the double or cumulene bond on at[prev_sb_neigh] */
    2539                 :             : 
    2540   [ #  #  #  # ]:           0 :             for (i = 0, num_other_neigh = 0; i < at[prev_sb_neigh].valence && num_other_neigh <= MAX_OTHER_NEIGH; i++)
    2541                 :             :             {
    2542         [ #  # ]:           0 :                 if (i != k)
    2543                 :             :                 {
    2544                 :             :                     /*  do not include the double or cumulene bond */
    2545                 :           0 :                     other_neigh[num_other_neigh++] = at[prev_sb_neigh].neighbor[i];
    2546                 :             :                 }
    2547                 :             :             }
    2548         [ #  # ]:           0 :             if (num_other_neigh + at[prev_sb_neigh].num_H > MAX_OTHER_NEIGH)
    2549                 :             :             {
    2550                 :           0 :                 return CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
    2551                 :             :             }
    2552         [ #  # ]:           0 :             for (i = 0; i < num_other_neigh; i++)
    2553                 :             :             {
    2554                 :           0 :                 k = (int) other_neigh[i];
    2555   [ #  #  #  # ]:           0 :                 if (nVisited1[k] && nVisited1[k] != nCanonRank[k])
    2556                 :             :                 {
    2557                 :           0 :                     return 0; /*  parity of the statring stereo bond/cumulene has not changed. */
    2558                 :             :                 }
    2559   [ #  #  #  # ]:           0 :                 if (nVisited2[k] && nVisited2[k] != nCanonRank[k])
    2560                 :             :                 {
    2561                 :           0 :                     return 0; /*  parity of the statring stereo bond/cumulene has not changed. */
    2562                 :             :                 }
    2563                 :             :             }
    2564                 :             :         }
    2565                 :             :     }
    2566                 :             : 
    2567         [ #  # ]:           0 :     if (nCheckingMode == CHECKING_STEREOCENTER)
    2568                 :             :     {
    2569                 :             :         /**************************************************
    2570                 :             :          *
    2571                 :             :          *  Possibly stereogenic starting atom at[cur]
    2572                 :             :          *
    2573                 :             :          **************************************************/
    2574                 :             :         /*  checking the starting stereo center */
    2575   [ #  #  #  # ]:           0 :         for (i = 0, num_other_neigh = 0; i < at[cur].valence && num_other_neigh <= MAX_OTHER_NEIGH; i++)
    2576                 :             :         {
    2577                 :           0 :             neigh = at[cur].neighbor[i];
    2578   [ #  #  #  # ]:           0 :             if (neigh != next1 && neigh != next2)
    2579                 :             :             {
    2580                 :           0 :                 other_neigh[num_other_neigh++] = neigh;
    2581                 :             :             }
    2582                 :             :         }
    2583         [ #  # ]:           0 :         if (num_other_neigh + at[cur].num_H > MAX_OTHER_NEIGH)
    2584                 :             :         {
    2585                 :           0 :             return CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
    2586                 :             :         }
    2587                 :             :         /*
    2588                 :             :         if ( bParitiesInverted && at[cur].valence == MAX_NUM_STEREO_ATOM_NEIGH ) {
    2589                 :             :             if ( nVisited1[other_neigh[0]] == nCanonRank[other_neigh[0]] ||
    2590                 :             :                  nVisited2[other_neigh[0]] == nCanonRank[other_neigh[0]] ||
    2591                 :             :                  nVisited1[other_neigh[1]] == nCanonRank[other_neigh[1]] ||
    2592                 :             :                  nVisited2[other_neigh[1]] == nCanonRank[other_neigh[1]] ) {
    2593                 :             :                 bParitiesInverted = 0;
    2594                 :             :                 bCurRotated = 1;
    2595                 :             :             }
    2596                 :             :         }
    2597                 :             :         */
    2598                 :             :         /* bParitiesInverted = -1 means no predefined stereocenter has been checked */
    2599   [ #  #  #  # ]:           0 :         if (bParitiesInverted && at[cur].valence == MAX_NUM_STEREO_ATOM_NEIGH)
    2600                 :             :         {
    2601                 :             :             /* special case: 4 canonically eq. neighbors */
    2602                 :             :             int canon_parity, parity_vis_1, parity_vis_2;
    2603                 :           0 :             canon_parity = GetPermutationParity( pCG, at + cur, MAX_ATOMS + 1, nCanonRank );
    2604                 :           0 :             parity_vis_1 = GetPermutationParity( pCG, at + cur, MAX_ATOMS + 1, nVisited1 );
    2605                 :           0 :             parity_vis_2 = GetPermutationParity( pCG, at + cur, MAX_ATOMS + 1, nVisited2 );
    2606         [ #  # ]:           0 :             if (parity_vis_1 != parity_vis_2)
    2607                 :             :             {
    2608                 :           0 :                 return 0;
    2609                 :             :             }
    2610   [ #  #  #  # ]:           0 :             if (bParitiesInverted == 1 && parity_vis_1 == canon_parity)
    2611                 :             :             {
    2612                 :           0 :                 return 0; /* not a typical case of inversion during the mapping of D4h stereocenter */
    2613                 :             :             }
    2614                 :             :             else
    2615                 :             :             {
    2616         [ #  # ]:           0 :                 if (bParitiesInverted == -1)
    2617                 :             :                 {
    2618         [ #  # ]:           0 :                     if (parity_vis_1 == canon_parity)
    2619                 :             :                     {
    2620                 :           0 :                         bParitiesInverted = 0;
    2621                 :             :                     }
    2622                 :             :                     else
    2623                 :             :                     {
    2624                 :           0 :                         bParitiesInverted = 1;
    2625                 :             :                     }
    2626                 :             :                 }
    2627                 :             :             }
    2628                 :             :         }
    2629                 :             :         /* at this point bParitiesInverted >= 0 */
    2630   [ #  #  #  # ]:           0 :         if (!bParitiesInverted && !bCurRotated)
    2631                 :             :         {
    2632         [ #  # ]:           0 :             for (i = 0; i < num_other_neigh; i++)
    2633                 :             :             {
    2634                 :           0 :                 k = (int) other_neigh[i];
    2635   [ #  #  #  # ]:           0 :                 if (nVisited1[k] && nVisited1[k] != nCanonRank[k])
    2636                 :             :                 {
    2637                 :           0 :                     return 0; /*  parity of the statring stereo center has not changed. */
    2638                 :             :                 }
    2639   [ #  #  #  # ]:           0 :                 if (nVisited2[k] && nVisited2[k] != nCanonRank[k])
    2640                 :             :                 {
    2641                 :           0 :                     return 0; /*  parity of the statring stereo center has not changed. */
    2642                 :             :                 }
    2643                 :             :             }
    2644                 :             :         }
    2645                 :             :     }
    2646                 :             : 
    2647                 :             :     /*****************************************************
    2648                 :             :      * Check other (non-starting) stereo centers
    2649                 :             :      ******************************************************/
    2650         [ #  # ]:           0 :     for (i = 0; i < pCS->nLenLinearCTStereoCarb; i++, nNumComparedCenters += ( k > 0 ))
    2651                 :             :     {
    2652                 :           0 :         r1 = pCS->LinearCTStereoCarb[i].at_num;
    2653                 :           0 :         i01 = nAtomNumberCanon[r1 - 1]; /*  ord. number of the atom that has canon rank r1 */
    2654                 :             : 
    2655                 :           0 :         i11 = nAtomNumberCanon1[r1 - 1]; /*  = (MAX_ATOMS+1) > num_atoms if the atom has not been traversed */
    2656                 :           0 :         i12 = nAtomNumberCanon2[r1 - 1]; /*  = otherwise < num_atoms */
    2657                 :             : 
    2658                 :           0 :         s1 = ( i11 < num_atoms ); /*  1 => the center was traversed on path #1 */
    2659                 :           0 :         s2 = ( i12 < num_atoms ); /*  1 => the center was traversed on path #2 */
    2660                 :             : 
    2661                 :           0 :         bCurParityInv1 = ( bParitiesInverted &&
    2662   [ #  #  #  # ]:           0 :                           at[cur].nRingSystem == at[i11].nRingSystem &&
    2663         [ #  # ]:           0 :                           at[cur].nRingSystem == at[i12].nRingSystem );
    2664                 :             : 
    2665                 :             : 
    2666                 :           0 :         k = 0;
    2667                 :             : 
    2668                 :             :         /*  check whether the two stereo centers (they can be one and the same atom) have been traversed */
    2669   [ #  #  #  # ]:           0 :         if (!s1 && !s2)
    2670                 :             :         {
    2671                 :           0 :             continue;  /*  Both stereo centers have not been traversed; check the next pair. */
    2672                 :             :         }
    2673                 :             : 
    2674         [ #  # ]:           0 :         if (nCheckingMode == CHECKING_STEREOCENTER)
    2675                 :             :         {
    2676                 :             :             /*  check whether the stereocenters are the starting stereocenter */
    2677      [ #  #  # ]:           0 :             switch (( cur == i11 ) + ( cur == i12 ))
    2678                 :             :             {
    2679                 :           0 :                 case 2:
    2680                 :           0 :                     continue; /*  do not recheck the starting atom */
    2681                 :           0 :                 case 1:
    2682                 :           0 :                     return -1; /*  possibly program error */ /*   <BRKPT> */
    2683                 :             :                 /* case 0: */
    2684                 :             :                 /*     break;  */  /*  the stereo centers are not the sarting stereo center */
    2685                 :             :             }
    2686         [ #  # ]:           0 :             if (cur == i01)
    2687                 :             :             {
    2688                 :           0 :                 return -1;  /*  program error: in this case at least one of the i11, i12 must be == cur */ /*   <BRKPT> */
    2689                 :             :             }
    2690                 :             :         }
    2691                 :             : 
    2692         [ #  # ]:           0 :         if (nNeighMode == NEIGH_MODE_RING)
    2693                 :             :         {
    2694   [ #  #  #  # ]:           0 :             if (i11 != i12 && !bCurParityInv1)
    2695                 :             :             {
    2696                 :           0 :                 return -1; /*  failed: the two stereo atoms have not been traversed synchronously */
    2697                 :             :             }
    2698   [ #  #  #  # ]:           0 :             if (!at[i11].parity || !at[i12].parity)
    2699                 :             :             {
    2700                 :           0 :                 return 0; /*  another atom does not have parity (it might have been removed) 9-11-2002 */
    2701                 :             :             }
    2702                 :             :         }
    2703         [ #  # ]:           0 :         if (nNeighMode == NEIGH_MODE_CHAIN)
    2704                 :             :         {
    2705         [ #  # ]:           0 :             if (s1 + s2 != 1)
    2706                 :             :             {
    2707                 :           0 :                 return -1; /*  program error: only one out of s1 and s2 must be 1, another must be 0. */
    2708                 :             :             }
    2709   [ #  #  #  #  :           0 :             if ((s1 && !at[i11].parity) || (s2 && !at[i12].parity)) /* djb-rwth: addressing LLVM warning */
             #  #  #  # ]
    2710                 :             :             {
    2711                 :           0 :                 return 0; /*  another atom does not have parity (it might have been removed) 9-11-2002 */
    2712                 :             :             }
    2713                 :             :         }
    2714                 :             : 
    2715                 :           0 :         parity = pCS->LinearCTStereoCarb[i].parity;
    2716   [ #  #  #  #  :           0 :         if (nNeighMode == (NEIGH_MODE_RING && ( i11 != i01 ) && ( i12 != i01 )) ||
             #  #  #  # ]
    2717                 :             :              /*  in NEIGH_MODE_RING case we know that i11 == i12 except bCurParityInv1 == 1 */
    2718                 :             :              nNeighMode == NEIGH_MODE_CHAIN
    2719                 :             :              /*  in NEIGH_MODE_CHAIN case here we always have 2 different atoms */
    2720                 :             :            ) /* djb-rwth: addressing LLVM warning */
    2721                 :             :         {
    2722                 :             :             /****************************************************************
    2723                 :             :             * Case of two transposed atoms or a circular permutation in D4h
    2724                 :             :             */
    2725         [ #  # ]:           0 :             parity1 = s1 ? GetStereoCenterParity( pCG, at, i11, nVisited1 ) : PARITY_IMPOSSIBLE;
    2726         [ #  # ]:           0 :             parity2 = s2 ? GetStereoCenterParity( pCG, at, i12, nVisited2 ) : PARITY_IMPOSSIBLE;
    2727   [ #  #  #  #  :           0 :             if (!ATOM_PARITY_KNOWN( parity1 ) && !ATOM_PARITY_KNOWN( parity2 ))
             #  #  #  # ]
    2728                 :             :             {
    2729                 :           0 :                 return -1; /*  should not happen: must have been detected at the time of the traversal */
    2730                 :             :             }
    2731   [ #  #  #  # ]:           0 :             if (s1 && s2)
    2732                 :             :             {
    2733         [ #  # ]:           0 :                 if (bCurParityInv1)
    2734                 :             :                 {
    2735                 :           0 :                     int parity1orig = GetStereoCenterParity( pCG, at, i11, nCanonRank );
    2736                 :           0 :                     int parity2orig = GetStereoCenterParity( pCG, at, i12, nCanonRank );
    2737   [ #  #  #  # ]:           0 :                     if (i11 == i12 ||
    2738   [ #  #  #  #  :           0 :                         (( parity1 == parity1orig || parity2 == parity2orig || parity1 != parity2 ) &&
                   #  # ]
    2739   [ #  #  #  # ]:           0 :                          ATOM_PARITY_WELL_DEF( parity1 )) ||
    2740   [ #  #  #  #  :           0 :                          ((parity1 != parity2 && ( !ATOM_PARITY_WELL_DEF( parity1 ))) ||
                   #  # ]
    2741         [ #  # ]:           0 :                              !ATOM_PARITY_WELL_DEF( parity2 ) )) /* djb-rwth: addressing LLVM warning */
    2742                 :             :                         /*return -1; */ /* should be different atoms with inverted parities */
    2743                 :           0 :                         nNumDiff++;
    2744                 :             :                 }
    2745                 :             :                 else
    2746                 :             :                 {
    2747   [ #  #  #  # ]:           0 :                     if (i11 != i12 || parity1 != parity2)
    2748                 :             :                     {
    2749                 :           0 :                         return -1; /*  program error: must be the same atom */
    2750                 :             :                     }
    2751                 :             :                 }
    2752                 :             :             }
    2753         [ #  # ]:           0 :             parity12 = s1 ? parity1 : parity2;
    2754                 :             : 
    2755   [ #  #  #  #  :           0 :             if (ATOM_PARITY_WELL_DEF( parity ) && parity == parity12)
                   #  # ]
    2756                 :             :             {
    2757                 :             :                 /*  symmetrical neighbors have well-defined equal parities */
    2758                 :           0 :                 k++;
    2759   [ #  #  #  # ]:           0 :                 if (nCheckingMode == CHECKING_STEREOCENTER && nNeighMode == NEIGH_MODE_RING)
    2760                 :             :                 {
    2761                 :             :                     /*  all 3: cur, i01, i11 are different atoms (here i11==i12) */
    2762                 :             :                     /*  here nSymmRank[i01]==nSymmRank[i11] due to the parallel traversal */
    2763         [ #  # ]:           0 :                     if (nSymmRank[cur] == nSymmRank[i01])
    2764                 :             :                     {
    2765                 :           0 :                         nNumEqStereogenic++;  /*  all 3 are equ */
    2766                 :             :                     }
    2767                 :             :                 }
    2768                 :             :             }
    2769                 :             :             else
    2770                 :             :             {
    2771   [ #  #  #  #  :           0 :                 if (ATOM_PARITY_WELL_DEF( parity ) && ATOM_PARITY_WELL_DEF( parity12 ))
             #  #  #  # ]
    2772                 :             :                 {
    2773                 :             :                     /*  apparently different well-defined parities */
    2774         [ #  # ]:           0 :                     if (!bCurParityInv1)
    2775                 :             :                     {
    2776                 :           0 :                         nNumInv++;
    2777                 :             :                         /* return 0; */
    2778                 :             :                     }
    2779                 :             :                 }
    2780                 :             :                 else
    2781                 :             :                 {
    2782                 :             : #if ( PROPAGATE_ILL_DEF_STEREO == 1 )
    2783                 :             :                     /*  at least one parity is ill-defined. Use parity1 and parity2 to temporarily save bitmaps */
    2784                 :           0 :                     parity1 = ( parity == vABParityUnknown /*AB_PARITY_UNKN*/ )
    2785                 :             :                         ? NOT_WELL_DEF_UNKN
    2786   [ #  #  #  # ]:           0 :                         : ( parity == AB_PARITY_UNDF ) ? NOT_WELL_DEF_UNDF : 0;
    2787                 :           0 :                     parity2 = ( parity12 == vABParityUnknown /*AB_PARITY_UNKN*/ )
    2788   [ #  #  #  # ]:           0 :                         ? NOT_WELL_DEF_UNKN : ( parity12 == AB_PARITY_UNDF ) ? NOT_WELL_DEF_UNDF : 0;
    2789         [ #  # ]:           0 :                     if (parity1 | parity2)
    2790                 :             :                     {
    2791                 :           0 :                         not_well_def_parities |= ( parity1 | parity2 );
    2792                 :           0 :                         k++;
    2793                 :             :                     }
    2794                 :             :                     else
    2795                 :             :                     {
    2796                 :           0 :                         return -1;  /*  program error */ /*   <BRKPT> */
    2797                 :             :                     }
    2798                 :             : #else
    2799                 :             :                     return 0;
    2800                 :             : #endif
    2801                 :             :                 }
    2802                 :             :             }
    2803                 :             :         }
    2804                 :             :         else
    2805                 :             :         {
    2806   [ #  #  #  # ]:           0 :             if (i11 == i01 && i12 == i01)
    2807                 :             :             {
    2808                 :             :                 /********************************************************************/
    2809                 :             :                 /*  i11 == i12 are same atom as i01, nNeighMode == NEIGH_MODE_RING */
    2810   [ #  #  #  # ]:           0 :                 if (!s1 || !s2)
    2811                 :             :                 {
    2812                 :           0 :                     return -1;
    2813                 :             :                 }
    2814                 :             :                 /*  the parity of the new neighbors permutation must be same as the old one */
    2815                 :             :                 /*  this must work for well-defined and ill-defined parities. */
    2816                 :             :                 /*  actual parity (that includes the geometry) is not important here. */
    2817                 :             :                 /*  old permutation */
    2818                 :           0 :                 parity = GetPermutationParity( pCG, at + i01, MAX_ATOMS + 1, nCanonRank );
    2819                 :             :                 /*  new parmutation */
    2820                 :           0 :                 parity1 = GetPermutationParity( pCG, at + i01, MAX_ATOMS + 1, nVisited1 );
    2821                 :           0 :                 parity2 = GetPermutationParity( pCG, at + i01, MAX_ATOMS + 1, nVisited2 );
    2822   [ #  #  #  # ]:           0 :                 if (parity != parity1 || parity != parity2)
    2823                 :             :                 {
    2824                 :           0 :                     return 0;
    2825                 :             :                 }
    2826                 :           0 :                 k++;
    2827                 :             :             }
    2828                 :             :             else
    2829                 :             :             {
    2830                 :             :                 /* nNeighMode == NEIGH_MODE_RING and only one out of the two (i11 == i01) (i12 == i01) is true */
    2831                 :           0 :                 return -1;
    2832                 :             :             }
    2833                 :             :         }
    2834                 :             :         /* nNumComparedCenters += (k > 0); */
    2835                 :             :     }
    2836   [ #  #  #  #  :           0 :     if (bCurRotated || nNumDiff || nNumInv)
                   #  # ]
    2837                 :             :     {
    2838                 :           0 :         return 0;
    2839                 :             :     }
    2840                 :             : 
    2841                 :             :      /* !!!! Add here bParitiesInverted == 1 case !!!! */
    2842                 :             :     /******************************************************/
    2843                 :             :     /*  Check other (non-starting) stereo bonds/cumulenes */
    2844                 :             :     /******************************************************/
    2845         [ #  # ]:           0 :     for (i = 0; i < pCS->nLenLinearCTStereoDble; i++, nNumComparedBonds += ( k > 0 ))
    2846                 :             :     {
    2847                 :           0 :         r1 = pCS->LinearCTStereoDble[i].at_num1;
    2848                 :           0 :         r2 = pCS->LinearCTStereoDble[i].at_num2;
    2849                 :           0 :         i01 = nAtomNumberCanon[r1 - 1];  /*  ord. number of the atom that originally has canon rank r1 */
    2850                 :           0 :         i02 = nAtomNumberCanon[r2 - 1];  /*  ord. number of the atom that originally has canon rank r2 */
    2851                 :             : 
    2852                 :           0 :         i11 = nAtomNumberCanon1[r1 - 1]; /*  ord. number of the atom that got canon rank r1 during the parallel traversal */
    2853                 :           0 :         i12 = nAtomNumberCanon1[r2 - 1]; /*  ord. number of the atom that got canon rank r2 during the parallel traversal */
    2854                 :             : 
    2855                 :           0 :         i21 = nAtomNumberCanon2[r1 - 1];
    2856                 :           0 :         i22 = nAtomNumberCanon2[r2 - 1];
    2857                 :             : 
    2858                 :             : 
    2859   [ #  #  #  # ]:           0 :         s1 = ( i11 < num_atoms && i12 < num_atoms );
    2860   [ #  #  #  # ]:           0 :         s2 = ( i21 < num_atoms && i22 < num_atoms );
    2861                 :             : 
    2862                 :           0 :         k = 0;
    2863                 :             : 
    2864                 :             :         /*  check whether the two stereo bonds/allenes (they can be one and the same) have been traversed */
    2865   [ #  #  #  # ]:           0 :         if (!s1 && !s2)
    2866                 :             :         {
    2867                 :           0 :             continue; /*  Both stereo bonds/cumulenes have not been traversed; check the next pair. */
    2868                 :             :         }
    2869                 :             : 
    2870         [ #  # ]:           0 :         if (nCheckingMode == CHECKING_STEREOBOND)
    2871                 :             :         {
    2872   [ #  #  #  #  :           0 :             switch (( (i11 == cur && i12 == prev_sb_neigh) || (i12 == cur && i11 == prev_sb_neigh) ) +
          #  #  #  #  #  
                   #  # ]
    2873   [ #  #  #  #  :           0 :                 ( (i21 == cur && i22 == prev_sb_neigh) || (i22 == cur && i21 == prev_sb_neigh) )) /* djb-rwth: addressing LLVM warning */
             #  #  #  # ]
    2874                 :             :             {
    2875                 :           0 :                 case 2:
    2876                 :           0 :                     continue; /*  do not recheck the starting bond/cumulene */
    2877                 :           0 :                 case 1:
    2878                 :           0 :                     return -1; /*  possibly program error  */ /*   <BRKPT> */
    2879                 :             :                 /* case 0: */
    2880                 :             :                 /*     break; */   /*  the stereo centers are not the sarting stereo center */
    2881                 :             :             }
    2882   [ #  #  #  #  :           0 :             if (( i01 == cur && i02 == prev_sb_neigh ) || ( i02 == cur && i01 == prev_sb_neigh ))
             #  #  #  # ]
    2883                 :             :             {
    2884                 :           0 :                 return -1;  /*  program error: in this case at least one of the i1x, i2x must be == cur */ /*   <BRKPT> */
    2885                 :             :             }
    2886                 :             :         }
    2887                 :             : 
    2888         [ #  # ]:           0 :         if (nNeighMode == NEIGH_MODE_RING)
    2889                 :             :         {
    2890   [ #  #  #  #  :           0 :             if (( i11 != i21 || i12 != i22 ) && ( i11 != i22 || i12 != i21 ))
             #  #  #  # ]
    2891                 :             :             {
    2892                 :           0 :                 return -1; /*  failed: the two bonds/cumulenes have not been traversed synchronously */
    2893                 :             :             }
    2894         [ #  # ]:           0 :             if (0 > GetStereoNeighborPos( at, i11, i12 ))
    2895                 :             :             {
    2896                 :           0 :                 return 0; /*  another bond is not stereo (the stereo might have been removed) 9-11-2002 */
    2897                 :             :             }
    2898                 :             :         }
    2899         [ #  # ]:           0 :         if (nNeighMode == NEIGH_MODE_CHAIN)
    2900                 :             :         {
    2901         [ #  # ]:           0 :             if (s1 + s2 != 1)
    2902                 :             :             {
    2903                 :           0 :                 return -1; /*  program error: only one out of s1 and s2 must be 1, another must be 0. */
    2904                 :             :             }
    2905   [ #  #  #  #  :           0 :             if ((s1 && 0 > GetStereoNeighborPos( at, i11, i12 )) ||
                   #  # ]
    2906         [ #  # ]:           0 :                  (s2 && 0 > GetStereoNeighborPos( at, i21, i22 ))) /* djb-rwth: addressing LLVM warning */
    2907                 :             :             {
    2908                 :           0 :                 return 0; /*  another bond is not stereo (the stereo might have been removed) 9-11-2002 */
    2909                 :             :             }
    2910                 :             :         }
    2911                 :             : 
    2912                 :           0 :         parity = pCS->LinearCTStereoDble[i].parity;
    2913                 :             :         /* bMustBeIdentical  = ATOM_PARITY_ILL_DEF(parity); */
    2914                 :             :         /* nNumEqStereogenic = 0; */
    2915                 :             : 
    2916   [ #  #  #  #  :           0 :         if ((nNeighMode == NEIGH_MODE_RING && ( i11 != i01 || i12 != i02 ) && ( i11 != i02 || i12 != i01 )) ||
          #  #  #  #  #  
                #  #  # ]
    2917                 :             :              nNeighMode == NEIGH_MODE_CHAIN                    /*  in NEIGH_MODE_CHAIN case here we always have 2 different atoms */
    2918                 :             :         ) /* djb-rwth: addressing LLVM warning */
    2919                 :             :         {
    2920                 :             :          /*******************************************/
    2921                 :             :          /*  case of two transposed bonds/cumulenes */
    2922         [ #  # ]:           0 :             parity1 = s1 ? GetStereoBondParity( at, i11, i12, nVisited1 ) : PARITY_IMPOSSIBLE;
    2923         [ #  # ]:           0 :             parity2 = s2 ? GetStereoBondParity( at, i21, i22, nVisited2 ) : PARITY_IMPOSSIBLE;
    2924   [ #  #  #  #  :           0 :             if (!ATOM_PARITY_KNOWN( parity1 ) && !ATOM_PARITY_KNOWN( parity2 ))
             #  #  #  # ]
    2925                 :             :             {
    2926                 :           0 :                 return -1; /*  should not happen: must have been detected at the time of traversal */
    2927                 :             :             }
    2928   [ #  #  #  #  :           0 :             if (s1 && s2 && ( (( i11 != i21 || i12 != i22 ) && ( i11 != i22 || i12 != i21 )) || parity1 != parity2 )) /* djb-rwth: addressing LLVM warning */
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2929                 :             :             {
    2930                 :           0 :                 return -1; /*  program error: must be the same bond/cumulene */
    2931                 :             :             }
    2932         [ #  # ]:           0 :             parity12 = s1 ? parity1 : parity2;
    2933   [ #  #  #  #  :           0 :             if (ATOM_PARITY_WELL_DEF( parity ) && parity == parity12)
                   #  # ]
    2934                 :             :             {
    2935                 :             :                 /*  symmetrical neighbors have well-defined equal parities */
    2936                 :           0 :                 k++;
    2937   [ #  #  #  # ]:           0 :                 if (nCheckingMode == CHECKING_STEREOBOND && nNeighMode == NEIGH_MODE_RING)
    2938                 :             :                 {
    2939                 :             :                     /*  all 3 bonds: cur-prev_sb_neigh, i01-i02, i11-i12 are different */
    2940                 :             :                     /*  (here <i11,i12>==<i21,i22> compared as unordered pairs) */
    2941   [ #  #  #  # ]:           0 :                     if ((nSymmRank[cur] == nSymmRank[i01] && nSymmRank[prev_sb_neigh] == nSymmRank[i02]) ||
    2942   [ #  #  #  # ]:           0 :                          (nSymmRank[cur] == nSymmRank[i02] && nSymmRank[prev_sb_neigh] == nSymmRank[i01])) /* djb-rwth: addressing LLVM warning */
    2943                 :             :                     {
    2944                 :           0 :                         nNumEqStereogenic++;
    2945                 :             :                     }
    2946                 :             :                 }
    2947                 :             :             }
    2948                 :             :             else
    2949                 :             :             {
    2950   [ #  #  #  #  :           0 :                 if (ATOM_PARITY_WELL_DEF( parity ) && ATOM_PARITY_WELL_DEF( parity12 ))
             #  #  #  # ]
    2951                 :             :                 {
    2952                 :             :                     /*  apparently different well-defined parities */
    2953                 :           0 :                     return 0;
    2954                 :             :                 }
    2955                 :             :                 else
    2956                 :             :                 {
    2957                 :             :                     /*  at least one parity is ill-defined. Use parity1 and parity2 to temporarily save bitmaps */
    2958                 :             : #if ( PROPAGATE_ILL_DEF_STEREO == 1 )
    2959         [ #  # ]:           0 :                     parity1 = ( parity == vABParityUnknown /*AB_PARITY_UNKN*/ ) ? NOT_WELL_DEF_UNKN :
    2960         [ #  # ]:           0 :                         ( parity == AB_PARITY_UNDF ) ? NOT_WELL_DEF_UNDF : 0;
    2961         [ #  # ]:           0 :                     parity2 = ( parity12 == vABParityUnknown /*AB_PARITY_UNKN*/ ) ? NOT_WELL_DEF_UNKN :
    2962         [ #  # ]:           0 :                         ( parity12 == AB_PARITY_UNDF ) ? NOT_WELL_DEF_UNDF : 0;
    2963         [ #  # ]:           0 :                     if (parity1 | parity2)
    2964                 :             :                     {
    2965                 :           0 :                         not_well_def_parities |= ( parity1 | parity2 );
    2966                 :           0 :                         k++;
    2967                 :             :                     }
    2968                 :             :                     else
    2969                 :             :                     {
    2970                 :           0 :                         return -1;  /*  program error */
    2971                 :             :                     }
    2972                 :             : #else
    2973                 :             :                     return 0;
    2974                 :             : #endif
    2975                 :             :                 }
    2976                 :             :             }
    2977                 :             :         }
    2978                 :             :         else
    2979                 :             :         {
    2980                 :             :             /*****************************************************************************************/
    2981                 :             :             /*  i11-i12 and i21-i22 are same as i01-i02 bond/cumulene, nNeighMode == NEIGH_MODE_RING */
    2982                 :             :             AT_NUMB n1, n2;
    2983                 :             :             int       j;
    2984   [ #  #  #  # ]:           0 :             if (!s1 || !s2)
    2985                 :             :             {
    2986                 :           0 :                 return -1;
    2987                 :             :             }
    2988                 :             :             /*  find neighbors along the stereo bond/cumulene */
    2989   [ #  #  #  # ]:           0 :             for (j = 0, n1 = MAX_ATOMS + 1; j < MAX_NUM_STEREO_BOND_NEIGH && at[i01].stereo_bond_neighbor[j]; j++)
    2990                 :             :             {
    2991         [ #  # ]:           0 :                 if ((int) at[i01].stereo_bond_neighbor[j] == i02 + 1)
    2992                 :             :                 {
    2993                 :           0 :                     n1 = at[i01].neighbor[(int) at[i01].stereo_bond_ord[j]];
    2994                 :           0 :                     break;
    2995                 :             :                 }
    2996                 :             :             }
    2997   [ #  #  #  # ]:           0 :             for (j = 0, n2 = MAX_ATOMS + 1; j < MAX_NUM_STEREO_BOND_NEIGH && at[i02].stereo_bond_neighbor[j]; j++)
    2998                 :             :             {
    2999         [ #  # ]:           0 :                 if ((int) at[i02].stereo_bond_neighbor[j] == i01 + 1)
    3000                 :             :                 {
    3001                 :           0 :                     n2 = at[i02].neighbor[(int) at[i02].stereo_bond_ord[j]];
    3002                 :           0 :                     break;
    3003                 :             :                 }
    3004                 :             :             }
    3005   [ #  #  #  # ]:           0 :             if (n1 > MAX_ATOMS || n2 > MAX_ATOMS)
    3006                 :             :             {
    3007                 :           0 :                 return CT_REMOVE_STEREO_ERR;
    3008                 :             :             }
    3009                 :             :             /*  the parity of the new neighbors permutation must be same as the old one */
    3010                 :             :             /*  this must work for well-defined and ill-defined parities. */
    3011                 :             :             /*  actual parity (that includes the geometry) is not important here. */
    3012                 :             :             /*  old permutation */
    3013                 :           0 :             parity = GetPermutationParity( pCG, at + i01, n1, nCanonRank ) + GetPermutationParity( pCG, at + i02, n2, nCanonRank );
    3014                 :             :             /*  new parmutation */
    3015                 :           0 :             parity1 = GetPermutationParity( pCG, at + i01, n1, nVisited1 ) + GetPermutationParity( pCG, at + i02, n2, nVisited1 );
    3016                 :           0 :             parity2 = GetPermutationParity( pCG, at + i01, n1, nVisited2 ) + GetPermutationParity( pCG, at + i02, n2, nVisited2 );
    3017   [ #  #  #  # ]:           0 :             if (parity % 2 != parity1 % 2 || parity1 % 2 != parity2 % 2)
    3018                 :             :             {
    3019                 :           0 :                 return 0;
    3020                 :             :             }
    3021                 :           0 :             k++;
    3022                 :             :         }
    3023                 :             : 
    3024                 :             :         /* nNumComparedBonds += ( k > 0 ); */
    3025                 :             :     }
    3026                 :             : 
    3027         [ #  # ]:           0 :     if (nNumEqStereogenic > 0)
    3028                 :             :     {
    3029                 :             : /*  case similar to trimethylcyclopropane: 3 constitutionally equivalent stereogenic elements */
    3030                 :             : /*  the transposition does not change the parities */
    3031                 :             : #if ( bRELEASE_VERSION == 0 )
    3032                 :             :         pCS->bExtract |= EXTR_2EQL2CENTER_TO_REMOVE_PARITY;
    3033                 :             : #endif
    3034                 :             : 
    3035                 :           0 :         return 0;
    3036                 :             :     }
    3037                 :             : 
    3038                 :             : 
    3039                 :             : /* =========================================================================================
    3040                 :             :     Note
    3041                 :             :     ====
    3042                 :             :     At this point the comparison is complete and no difference sufficient to establish
    3043                 :             :     absence of stereo parity has been found.
    3044                 :             :     However, non-zero not_well_def_parities means that an ill-defined parity was
    3045                 :             :     compared to an ill-defined or well-defined parity. This means that the parity
    3046                 :             :     of the atom or bond being checked cannot be well-defined anymore.
    3047                 :             : ========================================================================================*/
    3048                 :             : 
    3049                 :             : 
    3050                 :           0 :     not_well_def_parities |= COMP_STEREO_SUCCESS;
    3051                 :             : 
    3052                 :           0 :     return not_well_def_parities;
    3053                 :             : 
    3054                 :             :    /*  Add 1 to indicate success. The stereogenic elements might have been */
    3055                 :             :    /*  removed while checking existence of the previous atom/bond stereo */
    3056                 :             :    /* return (nNumComparedCenters + nNumComparedBonds + 1);  */
    3057                 :             : }
    3058                 :             : 
    3059                 :             : 
    3060                 :             : /********************************************************************************/
    3061                 :             : /*  Remove stereo marks from the bonds that are calculated to be non-stereo     */
    3062                 :             : /*  Such bonds must have 2 constitutionally equivalent attachments              */
    3063                 :             : /*  (can find two canonical numberings that change only one stereo bond parity) */
    3064                 :         109 : int RemoveCalculatedNonStereoBondParities( CANON_GLOBALS *pCG,
    3065                 :             :                                            sp_ATOM *at, int num_atoms,
    3066                 :             :                                            int num_at_tg,
    3067                 :             :                                            AT_RANK **pRankStack1,
    3068                 :             :                                            AT_RANK **pRankStack2,
    3069                 :             :                                            AT_RANK *nTempRank,
    3070                 :             :                                            NEIGH_LIST *NeighList,
    3071                 :             :                                            AT_RANK *nCanonRank,
    3072                 :             :                                            const AT_RANK *nSymmRank,
    3073                 :             :                                            AT_RANK *nAtomNumberCanon,
    3074                 :             :                                            AT_RANK *nAtomNumberCanon1,
    3075                 :             :                                            AT_RANK *nAtomNumberCanon2,
    3076                 :             :                                            NEIGH_LIST *nl,
    3077                 :             :                                            NEIGH_LIST *nl1,
    3078                 :             :                                            NEIGH_LIST *nl2,
    3079                 :             :                                            AT_RANK *nVisited1,
    3080                 :             :                                            AT_RANK *nVisited2,
    3081                 :             :                                            CANON_STAT *pCS,
    3082                 :             :                                            int vABParityUnknown )
    3083                 :             : {
    3084                 :         109 :     int j, n, m, ret, ret1, ret2, ret_failed = 0;
    3085                 :             : 
    3086                 :             :     int i1, n1, s2;  /*  n1 must be SIGNED integer */
    3087                 :         109 :     AT_RANK nAtomRank1, nAtomRank2, neigh[3] = { 0 }, nAvoidCheckAtom[2], opposite_atom, nLength; /* djb-rwth: initialisation of neigh required to avoid undefined array subscript */
    3088                 :         109 :     int         nNeighMode = NEIGH_MODE_CHAIN;
    3089                 :         109 :     int         nNumEqRingNeigh = 0, bRingNeigh, bSymmNeigh, bParitiesInverted;
    3090                 :             :     NEIGH_LIST *nl01, *nl02;
    3091                 :             :     const AT_RANK    *nSymmRank1, *nSymmRank2;
    3092                 :             : 
    3093                 :         109 :     ret = 0;
    3094                 :             : 
    3095                 :         109 : second_pass:
    3096                 :             : 
    3097   [ +  +  -  +  :        1215 :     for (i1 = 0; i1 < num_atoms && !RETURNED_ERROR(ret_failed); i1++)
                   +  - ]
    3098                 :             :     {
    3099   [ +  +  +  - ]:        1106 :         if (at[i1].valence != 3 || !at[i1].stereo_bond_neighbor[0])
    3100                 :             :         {
    3101                 :        1106 :             continue;
    3102                 :             :         }
    3103   [ #  #  #  #  :           0 :         for (n1 = 0; n1 < MAX_NUM_STEREO_BONDS && !RETURNED_ERROR(ret_failed) && (s2 = at[i1].stereo_bond_neighbor[n1]); n1++)
             #  #  #  # ]
    3104                 :             :         {
    3105   [ #  #  #  #  :           0 :             if (!PARITY_CALCULATE(at[i1].stereo_bond_parity[n1]) && PARITY_WELL_DEF(at[i1].stereo_bond_parity[n1]))
                   #  # ]
    3106                 :             :             {
    3107                 :           0 :                 continue;
    3108                 :             :             }
    3109                 :           0 :             opposite_atom = (AT_RANK)(s2 - 1);
    3110                 :           0 :             s2 = at[i1].neighbor[(int)at[i1].stereo_bond_ord[n1]]; /*  different from opposite_atom in case of a cumulene */
    3111         [ #  # ]:           0 :             for (j = 1, n = 0; j <= (int)at[i1].valence; j++)
    3112                 :             :             {
    3113         [ #  # ]:           0 :                 if (nl[i1][j] != s2)
    3114                 :             :                 {
    3115                 :           0 :                     neigh[n++] = nl[i1][j]; /*  sorting guarantees that canon. rank of neigh[0] is greater or equal */
    3116                 :             :                 }
    3117                 :             :             }
    3118         [ #  # ]:           0 :             if (n != 2)
    3119                 :             :             {
    3120                 :           0 :                 ret = CT_STEREOBOND_ERROR;  /*   <BRKPT> */
    3121                 :           0 :                 goto exit_function;
    3122                 :             :             }
    3123         [ #  # ]:           0 :             if (nSymmRank[(int)neigh[0]] != nSymmRank[(int)neigh[1]])
    3124                 :             :             {
    3125                 :           0 :                 continue; /*  may happen if another half-bond has not a defined parity */
    3126                 :             :             }
    3127                 :             : 
    3128                 :           0 :             bRingNeigh = (at[(int)neigh[0]].nRingSystem == at[(int)neigh[1]].nRingSystem);
    3129      [ #  #  # ]:           0 :             switch (nNeighMode)
    3130                 :             :             {
    3131                 :           0 :             case NEIGH_MODE_CHAIN:
    3132         [ #  # ]:           0 :                 if (bRingNeigh)
    3133                 :             :                 {
    3134                 :           0 :                     nNumEqRingNeigh++;
    3135                 :           0 :                     continue;
    3136                 :             :                 }
    3137                 :           0 :                 nl01 = nl;
    3138                 :           0 :                 nl02 = nl;
    3139                 :           0 :                 nSymmRank1 = nSymmRank;
    3140                 :           0 :                 nSymmRank2 = nSymmRank;
    3141                 :           0 :                 break;
    3142                 :             : 
    3143                 :           0 :             case NEIGH_MODE_RING:
    3144         [ #  # ]:           0 :                 if (!bRingNeigh)
    3145                 :           0 :                     continue;
    3146                 :             :                 /*  break a tie between the two contitutionally equivalent neighbors, */
    3147                 :             :                 /*  refine the two partitions, sort neighbors lists nl1, nl2 */
    3148                 :             : 
    3149                 :           0 :                 bSymmNeigh = BreakNeighborsTie(pCG,
    3150                 :             :                     at, num_atoms, num_at_tg,
    3151                 :             :                     opposite_atom, i1,
    3152                 :             :                     neigh, 0, 1, 0,
    3153                 :             :                     pRankStack1, pRankStack2, nTempRank,
    3154                 :             :                     NeighList, nSymmRank, nCanonRank,
    3155                 :             :                     nl1, nl2, &pCS->lNumNeighListIter);
    3156                 :             : 
    3157         [ #  # ]:           0 :                 if (bSymmNeigh <= 0)
    3158                 :             :                 {
    3159         [ #  # ]:           0 :                     if (ret_failed > bSymmNeigh)
    3160                 :           0 :                         ret_failed = bSymmNeigh;
    3161                 :           0 :                     continue;
    3162                 :             :                 }
    3163                 :           0 :                 nl01 = nl1;
    3164                 :           0 :                 nl02 = nl2;
    3165                 :           0 :                 nSymmRank1 = pRankStack1[0];
    3166                 :           0 :                 nSymmRank2 = pRankStack2[0];
    3167                 :           0 :                 break;
    3168                 :           0 :             default:
    3169                 :           0 :                 return CT_STEREOCOUNT_ERR;  /*  <BRKPT> */
    3170                 :             :             }
    3171                 :             : 
    3172                 :             :             /*  initialize arrays */
    3173                 :           0 :             memset(nVisited1, 0, sizeof(nVisited1[0]) * num_atoms); /* djb-rwth: memset_s C11/Annex K variant? */
    3174                 :           0 :             memset(nVisited2, 0, sizeof(nVisited2[0]) * num_atoms); /* djb-rwth: memset_s C11/Annex K variant? */
    3175                 :           0 :             memset(nAtomNumberCanon1, 0, sizeof(nAtomNumberCanon1[0]) * num_atoms); /* djb-rwth: memset_s C11/Annex K variant? */
    3176                 :           0 :             memset(nAtomNumberCanon2, 0, sizeof(nAtomNumberCanon2[0]) * num_atoms); /* djb-rwth: memset_s C11/Annex K variant? */
    3177                 :           0 :             nLength = 1;
    3178                 :           0 :             nVisited1[i1] = i1 + 1;   /*  start atoms are the same */
    3179                 :           0 :             nVisited2[i1] = i1 + 1;
    3180                 :           0 :             nAtomNumberCanon1[i1] = nLength;
    3181                 :           0 :             nAtomNumberCanon2[i1] = nLength;
    3182                 :           0 :             nAvoidCheckAtom[0] = i1;
    3183                 :           0 :             nAvoidCheckAtom[1] = opposite_atom;
    3184                 :           0 :             bParitiesInverted = (nNeighMode == NEIGH_MODE_RING &&
    3185         [ #  # ]:           0 :                 IS_ALLENE_CHAIN(at[i1].stereo_bond_parity[n1]) &&
    3186         [ #  # ]:           0 :                 PARITY_CALCULATE(at[i1].stereo_bond_parity[n1]) &&
    3187         [ #  # ]:           0 :                 at[i1].nRingSystem == at[opposite_atom].nRingSystem &&
    3188   [ #  #  #  # ]:           0 :                 at[opposite_atom].valence == MAX_NUM_STEREO_BONDS) ? -1 : 0;
    3189                 :             :             /* djb-rwth: removing redundant code */
    3190                 :             : 
    3191                 :             :             /* djb-rwth: restructuring code to avoid garbage values -- discussion required */
    3192                 :             : 
    3193                 :           0 :             ret1 = CreateCheckSymmPaths(at, (AT_RANK)i1, neigh[0], (AT_RANK)i1, neigh[1], nAvoidCheckAtom,
    3194                 :             :                 nVisited1, nVisited2, nAtomNumberCanon1, nAtomNumberCanon2,
    3195                 :             :                 nl01, nl02, nSymmRank1, nSymmRank2, nCanonRank, &nLength, &bParitiesInverted, 0);
    3196                 :           0 :             ret2 = CalculatedPathsParitiesAreIdentical(pCG, at, num_atoms, nSymmRank,
    3197                 :             :                 nCanonRank, nAtomNumberCanon, nAtomNumberCanon1, nAtomNumberCanon2,
    3198                 :           0 :                 nVisited1, nVisited2, opposite_atom, (AT_RANK)i1,
    3199                 :           0 :                 neigh[0], neigh[1], nNeighMode, bParitiesInverted, 0,
    3200                 :             :                 pCS, vABParityUnknown);
    3201                 :             : 
    3202         [ #  # ]:           0 :             if (0 < ret1) /* djb-rwth: or is this (0 < ret1) && (0 < ret2) ? */
    3203                 :             :             {
    3204         [ #  # ]:           0 :                 if (0 < ret2)
    3205                 :             :                 {
    3206                 :             :                     {
    3207         [ #  # ]:           0 :                         if (ret2 & (NOT_WELL_DEF_UNKN | NOT_WELL_DEF_UNDF))
    3208                 :             :                         {
    3209                 :             :                             /*  possibly change the parity to unknown or undefined */
    3210         [ #  # ]:           0 :                             int new_parity = (ret2 & NOT_WELL_DEF_UNKN) ? vABParityUnknown /*AB_PARITY_UNKN*/ : AB_PARITY_UNDF;
    3211   [ #  #  #  #  :           0 :                             if ((PARITY_ILL_DEF(at[i1].stereo_bond_parity[n1]) && PARITY_VAL(at[i1].stereo_bond_parity[n1]) > new_parity) ||
                   #  # ]
    3212         [ #  # ]:           0 :                                 PARITY_CALCULATE(at[i1].stereo_bond_parity[n1])) /* djb-rwth: addressing LLVM warning */
    3213                 :             :                             {
    3214                 :             :                                 /*  set new unknown or undefined parity */
    3215                 :           0 :                                 SetOneStereoBondIllDefParity(at, i1, /* atom number*/ n1 /* stereo bond ord. number*/, new_parity);
    3216                 :             :                                 /*  change in pCS */
    3217                 :           0 :                                 nAtomRank1 = inchi_max(nCanonRank[i1], nCanonRank[opposite_atom]);
    3218                 :           0 :                                 nAtomRank2 = inchi_min(nCanonRank[i1], nCanonRank[opposite_atom]);
    3219         [ #  # ]:           0 :                                 for (n = 0, m = pCS->nLenLinearCTStereoDble - 1; n <= m; n++)
    3220                 :             :                                 {
    3221         [ #  # ]:           0 :                                     if (pCS->LinearCTStereoDble[n].at_num1 == nAtomRank1 &&
    3222         [ #  # ]:           0 :                                         pCS->LinearCTStereoDble[n].at_num2 == nAtomRank2)
    3223                 :             :                                     {
    3224                 :           0 :                                         pCS->LinearCTStereoDble[n].parity = new_parity;
    3225                 :             : #if ( bRELEASE_VERSION == 0 )
    3226                 :             :                                         pCS->bExtract |= EXTR_CALC_USED_TO_REMOVE_PARITY;
    3227                 :             : #endif
    3228                 :           0 :                                         m = -1;
    3229                 :           0 :                                         break;
    3230                 :             :                                     }
    3231                 :             :                                 }
    3232         [ #  # ]:           0 :                                 if (m >= 0)
    3233                 :             :                                 {
    3234                 :           0 :                                     ret = CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
    3235                 :           0 :                                     goto exit_function;
    3236                 :             :                                 }
    3237                 :           0 :                                 ret++;
    3238                 :             :                             }
    3239                 :             :                         }
    3240                 :             :                         else
    3241                 :             :                         {
    3242                 :             :                             /*  remove the parity */
    3243         [ #  # ]:           0 :                             if (!RemoveOneStereoBond(at, i1, /* atom number*/ n1 /* stereo bond ord. number*/))
    3244                 :             :                             {
    3245                 :           0 :                                 ret = CT_STEREOBOND_ERROR;  /*   <BRKPT> */
    3246                 :           0 :                                 goto exit_function;
    3247                 :             :                             }
    3248                 :           0 :                             n1--;  /*  cycle counter may temporarily become negative */
    3249                 :             :                             /*  Remove from the pCS */
    3250                 :           0 :                             nAtomRank1 = inchi_max(nCanonRank[i1], nCanonRank[opposite_atom]);
    3251                 :           0 :                             nAtomRank2 = inchi_min(nCanonRank[i1], nCanonRank[opposite_atom]);
    3252         [ #  # ]:           0 :                             for (n = 0, m = pCS->nLenLinearCTStereoDble - 1; n <= m; n++)
    3253                 :             :                             {
    3254         [ #  # ]:           0 :                                 if (pCS->LinearCTStereoDble[n].at_num1 == nAtomRank1 &&
    3255         [ #  # ]:           0 :                                     pCS->LinearCTStereoDble[n].at_num2 == nAtomRank2)
    3256                 :             :                                 {
    3257         [ #  # ]:           0 :                                     if (n < m)
    3258                 :             :                                     {
    3259                 :             :                                         /*  remove pCS->LinearCTStereoDble[n] */
    3260                 :           0 :                                         memmove(pCS->LinearCTStereoDble + n,
    3261                 :           0 :                                             pCS->LinearCTStereoDble + n + 1,
    3262                 :           0 :                                             ((long long)m - (long long)n) * sizeof(pCS->LinearCTStereoDble[0])); /* djb-rwth: cast operators added */
    3263                 :             :                                     }
    3264                 :           0 :                                     pCS->nLenLinearCTStereoDble--;
    3265                 :             : #if ( bRELEASE_VERSION == 0 )
    3266                 :             :                                     pCS->bExtract |= EXTR_CALC_USED_TO_REMOVE_PARITY;
    3267                 :             : #endif
    3268                 :           0 :                                     m = -1;
    3269                 :           0 :                                     break;
    3270                 :             :                                 }
    3271                 :             :                             }
    3272         [ #  # ]:           0 :                             if (m >= 0)
    3273                 :             :                             {
    3274                 :           0 :                                 ret = CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
    3275                 :           0 :                                 goto exit_function;
    3276                 :             :                             }
    3277                 :           0 :                             ret++;
    3278                 :             :                         }
    3279                 :             :                     }
    3280                 :             :                 }
    3281                 :             :                 else
    3282                 :             :                 {
    3283         [ #  # ]:           0 :                     if (!ret_failed)
    3284                 :             :                     {
    3285         [ #  # ]:           0 :                         ret_failed = (ret1 < 0) ? ret1 : (ret2 < 0) ? ret2 : 0;
    3286                 :             :                     }
    3287   [ #  #  #  # ]:           0 :                     if (!RETURNED_ERROR(ret_failed))
    3288                 :             :                     {
    3289   [ #  #  #  # ]:           0 :                         if (RETURNED_ERROR(ret1))
    3290                 :             :                         {
    3291                 :           0 :                             ret_failed = ret1;
    3292                 :             :                         }
    3293                 :             :                         else
    3294                 :             :                         {
    3295   [ #  #  #  # ]:           0 :                             if (RETURNED_ERROR(ret2))
    3296                 :             :                             {
    3297                 :           0 :                                 ret_failed = ret2;
    3298                 :             :                             }
    3299                 :             :                         }
    3300                 :             :                     }
    3301                 :             :                 }
    3302                 :             :             }
    3303                 :             :         }
    3304                 :             :     }
    3305                 :             : 
    3306   [ +  -  +  -  :         109 :     if (nNeighMode == NEIGH_MODE_CHAIN && nNumEqRingNeigh && !RETURNED_ERROR( ret_failed ))
             -  -  -  - ]
    3307                 :             :     {
    3308                 :           0 :         nNeighMode = NEIGH_MODE_RING;
    3309                 :           0 :         goto second_pass;
    3310                 :             :     }
    3311                 :             : 
    3312                 :         109 : exit_function:
    3313                 :             : 
    3314   [ +  -  +  -  :         109 :     return RETURNED_ERROR( ret_failed ) ? ret_failed : ret_failed ? -( ret_failed + 1 ) : ret;
                   -  + ]
    3315                 :             : }
    3316                 :             : 
    3317                 :             : 
    3318                 :             : /****************************************************************************/
    3319                 :             : /*  Remove stereo marks from the atoms that are calculated to be non-stereo */
    3320                 :             : /*  (can find two numberings that change only one stereo center parity)     */
    3321                 :         109 : int RemoveCalculatedNonStereoCenterParities( CANON_GLOBALS *pCG,
    3322                 :             :                                              sp_ATOM *at,
    3323                 :             :                                              int num_atoms,
    3324                 :             :                                              int num_at_tg,
    3325                 :             :                                              AT_RANK **pRankStack1,
    3326                 :             :                                              AT_RANK **pRankStack2,
    3327                 :             :                                              AT_RANK *nTempRank,
    3328                 :             :                                              NEIGH_LIST *NeighList,
    3329                 :             :                                              AT_RANK *nCanonRank,
    3330                 :             :                                              const AT_RANK *nSymmRank,
    3331                 :             :                                              AT_RANK *nAtomNumberCanon,
    3332                 :             :                                              AT_RANK *nAtomNumberCanon1,
    3333                 :             :                                              AT_RANK *nAtomNumberCanon2,
    3334                 :             :                                              NEIGH_LIST *nl,
    3335                 :             :                                              NEIGH_LIST *nl1,
    3336                 :             :                                              NEIGH_LIST *nl2,
    3337                 :             :                                              AT_RANK *nVisited1,
    3338                 :             :                                              AT_RANK *nVisited2,
    3339                 :             :                                              CANON_STAT *pCS,
    3340                 :             :                                              int vABParityUnknown )
    3341                 :             : {
    3342                 :             :     int j, n, m, ret;
    3343                 :             : 
    3344                 :         109 :     int i, k, ret1, ret2, ret_failed = 0, mode, max_mode;
    3345                 :         109 :     AT_RANK nAtomRank1, neigh[MAX_NUM_STEREO_ATOM_NEIGH] = { 0 }, nAvoidCheckAtom[2], nLength; /* djb-rwth: initialisation of neigh required to avoid undefined array subscript */
    3346                 :         109 :     int         nNeighMode = NEIGH_MODE_CHAIN;
    3347                 :         109 :     int         nNumEqRingNeigh = 0, bRingNeigh, bSymmNeigh, bParitiesInverted;
    3348                 :             :     NEIGH_LIST *nl01, *nl02;
    3349                 :             :     const AT_RANK    *nSymmRank1, *nSymmRank2;
    3350                 :             : 
    3351                 :         109 :     ret = 0;
    3352                 :             : 
    3353                 :         109 : second_pass:
    3354                 :             : 
    3355   [ +  +  -  +  :        1215 :     for (i = 0; i < num_atoms && !RETURNED_ERROR( ret_failed ); i++)
                   +  - ]
    3356                 :             :     {
    3357   [ +  +  -  + ]:        1106 :         if (!at[i].parity || at[i].stereo_bond_neighbor[0])
    3358                 :             :         {
    3359                 :         739 :             continue;
    3360                 :             :         }
    3361                 :             : 
    3362         [ -  + ]:         367 :         if (at[i].valence > MAX_NUM_STEREO_ATOM_NEIGH)
    3363                 :             :         {
    3364                 :           0 :             continue; /*  error: stereo center cannot have more than 4 neighbors */ /*   <BRKPT> */
    3365                 :             :         }
    3366                 :             : 
    3367                 :             :         /*  at[i1] is a stereo center */
    3368   [ +  -  +  +  :         367 :         if (!PARITY_CALCULATE( at[i].stereo_atom_parity ) && !PARITY_ILL_DEF( at[i].stereo_atom_parity ))
                   -  + ]
    3369                 :             :         {
    3370                 :         334 :             continue;
    3371                 :             :         }
    3372                 :             : 
    3373                 :             :         /* neighbors sorted according to symm. ranks (primary key) and canon. ranks (secondary key), in descending order */
    3374                 :             :         /* sorting guarantees that for two constit. equ. neighbors canon. ranks of the first is greater */
    3375                 :             :         /* !!! previously (but not anymore) the canon. rank of neigh[0] was greater than the others !!! */
    3376         [ +  + ]:         132 :         for (j = 0; j < at[i].valence; j++)
    3377                 :             :         {
    3378                 :          99 :             neigh[j] = nl[i][j + 1]; /*  sorting does NOT guarantee that canon. rank of neigh[0] is greater than others */
    3379                 :             :         }
    3380                 :             : 
    3381                 :             :         /*
    3382                 :             :          *  mode = 0 => Standard approach: switch 2 neighbors
    3383                 :             :          *         1 => Check for C2v reflection leading to parity inversion
    3384                 :             :          *         2 => Check for C2 rotation preserving parities
    3385                 :             :          *         3 => Check for S4 rotation/reflection leading to parity inversion
    3386                 :             :          */
    3387                 :             : 
    3388                 :             : #if ( CHECK_C2v_S4_SYMM == 1 )
    3389                 :             :         if (nNeighMode = NEIGH_MODE_RING && at[i].valence == 4 &&
    3390                 :             :              nSymmRank[(int) neigh[0]] == nSymmRank[(int) neigh[1]] &&
    3391                 :             :              nSymmRank[(int) neigh[2]] == nSymmRank[(int) neigh[3]] &&
    3392                 :             :              !at[i].bCutVertex
    3393                 :             :            )
    3394                 :             :         {
    3395                 :             :             if (nSymmRank[(int) neigh[1]] == nSymmRank[(int) neigh[2]])
    3396                 :             :             {
    3397                 :             :                 max_mode = MAP_MODE_S4;
    3398                 :             :             }
    3399                 :             :             else
    3400                 :             :             {
    3401                 :             :                 max_mode = inchi_max( MAP_MODE_C2v, MAP_MODE_C2 );
    3402                 :             :             }
    3403                 :             :         }
    3404                 :             :         else
    3405                 :             :         {
    3406                 :             :             max_mode = MAP_MODE_STD;
    3407                 :             :         }
    3408                 :             : #else
    3409                 :          33 :         max_mode = MAP_MODE_STD;
    3410                 :             : #endif
    3411                 :             : 
    3412   [ +  +  +  -  :         132 :         for (j = 0; j < at[i].valence && at[i].parity && !RETURNED_ERROR( ret_failed ); j++)
             -  +  +  - ]
    3413                 :             :         {
    3414   [ +  +  +  -  :         198 :             for (k = j + 1; k < at[i].valence && at[i].parity && !RETURNED_ERROR( ret_failed ); k++)
             -  +  +  - ]
    3415                 :             :             {
    3416   [ +  +  +  -  :         198 :                 for (mode = 0; mode <= max_mode && at[i].parity && !RETURNED_ERROR(ret_failed); mode++)
             -  +  +  - ]
    3417                 :             :                 {
    3418         [ +  - ]:          99 :                     if (nSymmRank[(int)neigh[j]] != nSymmRank[(int)neigh[k]])
    3419                 :             :                     {
    3420                 :          99 :                         continue; /*  the two neighbors are not constitutionally identical */
    3421                 :             :                     }
    3422                 :           0 :                     bRingNeigh = (at[(int)neigh[j]].nRingSystem == at[(int)neigh[k]].nRingSystem);
    3423      [ #  #  # ]:           0 :                     switch (nNeighMode)
    3424                 :             :                     {
    3425                 :           0 :                     case NEIGH_MODE_CHAIN:
    3426         [ #  # ]:           0 :                         if (bRingNeigh)
    3427                 :             :                         {
    3428                 :           0 :                             nNumEqRingNeigh++;
    3429                 :           0 :                             continue;
    3430                 :             :                         }
    3431                 :           0 :                         nl01 = nl;
    3432                 :           0 :                         nl02 = nl;
    3433                 :           0 :                         nSymmRank1 = nSymmRank;
    3434                 :           0 :                         nSymmRank2 = nSymmRank;
    3435                 :           0 :                         break;
    3436                 :           0 :                     case NEIGH_MODE_RING:
    3437         [ #  # ]:           0 :                         if (!bRingNeigh)
    3438                 :           0 :                             continue;
    3439                 :             :                         /*  break a tie between the two contitutionally equivalent neighbors, */
    3440                 :             :                         /*  refine the two partitions, sort neighbors lists nl1, nl2 */
    3441                 :           0 :                         bSymmNeigh = BreakNeighborsTie(pCG, at, num_atoms, num_at_tg, MAX_ATOMS + 1, i,
    3442                 :             :                             neigh, j, k, mode,
    3443                 :             :                             pRankStack1, pRankStack2, nTempRank, NeighList, nSymmRank, nCanonRank,
    3444                 :             :                             nl1, nl2, &pCS->lNumNeighListIter);
    3445         [ #  # ]:           0 :                         if (bSymmNeigh <= 0)
    3446                 :             :                         {
    3447         [ #  # ]:           0 :                             if (ret_failed > bSymmNeigh)
    3448                 :           0 :                                 ret_failed = bSymmNeigh;
    3449                 :           0 :                             continue;
    3450                 :             :                         }
    3451                 :           0 :                         nl01 = nl1;
    3452                 :           0 :                         nl02 = nl2;
    3453                 :           0 :                         nSymmRank1 = pRankStack1[0];
    3454                 :           0 :                         nSymmRank2 = pRankStack2[0];
    3455                 :           0 :                         break;
    3456                 :           0 :                     default:
    3457                 :           0 :                         return CT_STEREOCOUNT_ERR;  /*  <BRKPT> */
    3458                 :             :                     }
    3459                 :             : 
    3460                 :             :                     /*  initialize arrays */
    3461                 :           0 :                     memset(nVisited1, 0, sizeof(nVisited1[0]) * num_atoms); /* djb-rwth: memset_s C11/Annex K variant? */
    3462                 :           0 :                     memset(nVisited2, 0, sizeof(nVisited2[0]) * num_atoms); /* djb-rwth: memset_s C11/Annex K variant? */
    3463                 :           0 :                     memset(nAtomNumberCanon1, 0, sizeof(nAtomNumberCanon1[0]) * num_atoms); /* djb-rwth: memset_s C11/Annex K variant? */
    3464                 :           0 :                     memset(nAtomNumberCanon2, 0, sizeof(nAtomNumberCanon2[0]) * num_atoms); /* djb-rwth: memset_s C11/Annex K variant? */
    3465                 :           0 :                     nLength = 1;
    3466                 :           0 :                     nVisited1[i] = i + 1;   /*  start atom is same */
    3467                 :           0 :                     nVisited2[i] = i + 1;
    3468                 :           0 :                     nAtomNumberCanon1[i] = nLength;
    3469                 :           0 :                     nAtomNumberCanon2[i] = nLength;
    3470                 :           0 :                     nAvoidCheckAtom[0] = i;
    3471                 :           0 :                     nAvoidCheckAtom[1] = MAX_ATOMS + 1;
    3472                 :             : 
    3473   [ #  #  #  # ]:           0 :                     bParitiesInverted = (mode == MAP_MODE_C2v || mode == MAP_MODE_S4) ? -1 : 0;
    3474                 :             : 
    3475                 :             :                     /*
    3476                 :             :                     if (nNeighMode==NEIGH_MODE_RING && at[i].valence==MAX_NUM_STEREO_ATOM_NEIGH) {
    3477                 :             :                         AT_RANK other_neigh[2];
    3478                 :             :                         int     n;
    3479                 :             :                         for ( m = n = 0; m < MAX_NUM_STEREO_ATOM_NEIGH; m ++ ) {
    3480                 :             :                             if ( at[i].neighbor[m] != neigh[j] && at[i].neighbor[m] != neigh[k] )
    3481                 :             :                                 other_neigh[n++] = at[i].neighbor[m];
    3482                 :             :                         }
    3483                 :             :                         if ( nSymmRank[(int)other_neigh[0]] == nSymmRank[(int)other_neigh[1]] )
    3484                 :             :                             bParitiesInverted = -1;
    3485                 :             :                     }
    3486                 :             :                     */
    3487                 :             : 
    3488                 :             :                     /* allow matching inverted centers only in case all equivalent neighbors in same ring system */
    3489                 :             : 
    3490                 :             :                     /* djb-rwth: restructuring code to avoid undefined array subscripts; removing unnecessary code; discussion required */
    3491                 :             : 
    3492                 :           0 :                     ret1 = CreateCheckSymmPaths(at, (AT_RANK)i, neigh[j], (AT_RANK)i, neigh[k], nAvoidCheckAtom,
    3493                 :             :                         nVisited1, nVisited2, nAtomNumberCanon1, nAtomNumberCanon2,
    3494                 :             :                         nl01, nl02, nSymmRank1, nSymmRank2, nCanonRank, &nLength,
    3495                 :             :                         &bParitiesInverted, mode);
    3496                 :           0 :                     ret2 = CalculatedPathsParitiesAreIdentical(pCG, at, num_atoms, nSymmRank,
    3497                 :             :                         nCanonRank, nAtomNumberCanon, nAtomNumberCanon1, nAtomNumberCanon2,
    3498                 :           0 :                         nVisited1, nVisited2, (AT_RANK)MAX_ATOMS, (AT_RANK)i,
    3499                 :           0 :                         neigh[j], neigh[k], nNeighMode,
    3500                 :             :                         bParitiesInverted, mode, pCS, vABParityUnknown);
    3501                 :             : 
    3502         [ #  # ]:           0 :                     if (0 < ret1) /* djb-rwth: or is this (0 < ret1) && (0 < ret2) ? */
    3503                 :             :                     {
    3504         [ #  # ]:           0 :                         if (0 < ret2)
    3505                 :             :                         {
    3506                 :             :                             {
    3507         [ #  # ]:           0 :                                 if (ret2 & (NOT_WELL_DEF_UNKN | NOT_WELL_DEF_UNDF))
    3508                 :             :                                 {
    3509                 :             :                                     /*  possibly change the parity to unknown or undefined */
    3510         [ #  # ]:           0 :                                     int new_parity = (ret2 & NOT_WELL_DEF_UNKN) ? vABParityUnknown /*AB_PARITY_UNKN*/ : AB_PARITY_UNDF;
    3511   [ #  #  #  # ]:           0 :                                     if ((PARITY_ILL_DEF(at[i].stereo_atom_parity) &&
    3512         [ #  # ]:           0 :                                         PARITY_VAL(at[i].stereo_atom_parity) > new_parity) ||
    3513         [ #  # ]:           0 :                                         PARITY_CALCULATE(at[i].stereo_atom_parity)) /* djb-rwth: addressing LLVM warning */
    3514                 :             :                                     {
    3515                 :             :                                         /*  set new unknown or undefined parity */
    3516                 :           0 :                                         at[i].stereo_atom_parity = (at[i].stereo_atom_parity ^ PARITY_VAL(at[i].stereo_atom_parity)) | PARITY_VAL(new_parity);
    3517                 :           0 :                                         at[i].parity = PARITY_VAL(new_parity);
    3518                 :             :                                         /*  Remove from pCS */
    3519                 :           0 :                                         nAtomRank1 = nCanonRank[i];
    3520         [ #  # ]:           0 :                                         for (n = 0, m = pCS->nLenLinearCTStereoCarb - 1; n <= m; n++)
    3521                 :             :                                         {
    3522         [ #  # ]:           0 :                                             if (pCS->LinearCTStereoCarb[n].at_num == nAtomRank1)
    3523                 :             :                                             {
    3524                 :           0 :                                                 pCS->LinearCTStereoCarb[n].parity = PARITY_VAL(new_parity);
    3525                 :             : #if ( bRELEASE_VERSION == 0 )
    3526                 :             :                                                 pCS->bExtract |= EXTR_CALC_USED_TO_REMOVE_PARITY;
    3527                 :             : #endif
    3528                 :           0 :                                                 m = -1;
    3529                 :           0 :                                                 break;
    3530                 :             :                                             }
    3531                 :             :                                         }
    3532         [ #  # ]:           0 :                                         if (m >= 0)
    3533                 :             :                                         {
    3534                 :           0 :                                             ret = CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
    3535                 :           0 :                                             goto exit_function;
    3536                 :             :                                         }
    3537                 :           0 :                                         ret++; /*  number of removed or set unknown/undefined parities */
    3538                 :             :                                     }
    3539                 :             :                                 }
    3540                 :             :                                 else
    3541                 :             :                                 {
    3542                 :             : #ifdef FIX_STEREOCOUNT_ERR
    3543         [ #  # ]:           0 :                                     if (at[i].stereo_atom_parity & KNOWN_PARITIES_EQL)
    3544                 :             :                                     {
    3545                 :             :                                         int jj;
    3546                 :           0 :                                         AT_RANK EqRank = pCS->nSymmRank[i];
    3547         [ #  # ]:           0 :                                         for (jj = 0; jj < num_atoms; jj++)
    3548                 :             :                                         {
    3549         [ #  # ]:           0 :                                             if (pCS->nSymmRank[jj] == EqRank)
    3550                 :             :                                             {
    3551                 :           0 :                                                 at[jj].stereo_atom_parity &= ~KNOWN_PARITIES_EQL;
    3552                 :             :                                             }
    3553                 :             :                                         }
    3554                 :             :                                     }
    3555                 :             : #endif
    3556                 :           0 :                                     RemoveOneStereoCenter(at, i /* atom number*/);
    3557                 :             :                                     /*  Remove from pCS */
    3558                 :           0 :                                     nAtomRank1 = nCanonRank[i];
    3559         [ #  # ]:           0 :                                     for (n = 0, m = pCS->nLenLinearCTStereoCarb - 1; n <= m; n++)
    3560                 :             :                                     {
    3561         [ #  # ]:           0 :                                         if (pCS->LinearCTStereoCarb[n].at_num == nAtomRank1)
    3562                 :             :                                         {
    3563         [ #  # ]:           0 :                                             if (n < m)
    3564                 :             :                                             {
    3565                 :             :                                                 /*  remove pCS->LinearCTStereoDble[n] */
    3566                 :           0 :                                                 memmove(pCS->LinearCTStereoCarb + n,
    3567                 :           0 :                                                     pCS->LinearCTStereoCarb + n + 1,
    3568                 :           0 :                                                     ((long long)m - (long long)n) * sizeof(pCS->LinearCTStereoCarb[0])); /* djb-rwth: cast operators added */
    3569                 :             :                                             }
    3570                 :           0 :                                             pCS->nLenLinearCTStereoCarb--;
    3571                 :             : #if ( bRELEASE_VERSION == 0 )
    3572                 :             :                                             pCS->bExtract |= EXTR_CALC_USED_TO_REMOVE_PARITY;
    3573                 :             : #endif
    3574                 :           0 :                                             m = -1;
    3575                 :           0 :                                             break;
    3576                 :             :                                         }
    3577                 :             :                                     }
    3578         [ #  # ]:           0 :                                     if (m >= 0)
    3579                 :             :                                     {
    3580                 :           0 :                                         ret = CT_STEREOCOUNT_ERR;  /*   <BRKPT> */
    3581                 :           0 :                                         goto exit_function;
    3582                 :             :                                     }
    3583                 :           0 :                                     ret++;  /*  number of removed or set unknown/undefined parities */
    3584                 :             :                                 }
    3585                 :             :                             }
    3586                 :             :                         }
    3587                 :             :                         else
    3588                 :             :                         {
    3589         [ #  # ]:           0 :                             if (!ret_failed)
    3590                 :             :                             {
    3591         [ #  # ]:           0 :                                 if (ret1 < 0)
    3592                 :             :                                 {
    3593                 :           0 :                                     ret_failed = ret1;
    3594                 :             :                                 }
    3595                 :             :                                 else
    3596                 :             :                                 {
    3597         [ #  # ]:           0 :                                     if (ret2 < 0)
    3598                 :             :                                     {
    3599                 :           0 :                                         ret_failed = ret2;
    3600                 :             :                                     }
    3601                 :             :                                 }
    3602                 :             :                             }
    3603   [ #  #  #  # ]:           0 :                             if (!RETURNED_ERROR(ret_failed))
    3604                 :             :                             {
    3605   [ #  #  #  # ]:           0 :                                 if (RETURNED_ERROR(ret1))
    3606                 :             :                                 {
    3607                 :           0 :                                     ret_failed = ret1;
    3608                 :             :                                 }
    3609                 :             :                                 else
    3610                 :             :                                 {
    3611   [ #  #  #  # ]:           0 :                                     if (RETURNED_ERROR(ret2))
    3612                 :             :                                     {
    3613                 :           0 :                                         ret_failed = ret2;
    3614                 :             :                                     }
    3615                 :             :                                 }
    3616                 :             :                             }
    3617                 :             :                         }
    3618                 :             :                     }
    3619                 :             :                 }
    3620                 :             :             }
    3621                 :             :         }
    3622                 :             :     }
    3623                 :             : 
    3624   [ +  -  +  -  :         109 :     if (nNeighMode == NEIGH_MODE_CHAIN && nNumEqRingNeigh && !RETURNED_ERROR( ret_failed ))
             -  -  -  - ]
    3625                 :             :     {
    3626                 :           0 :         nNeighMode = NEIGH_MODE_RING;
    3627                 :           0 :         goto second_pass;
    3628                 :             :     }
    3629                 :             : 
    3630                 :         109 : exit_function:
    3631                 :             : 
    3632   [ +  -  +  -  :         109 :     return RETURNED_ERROR( ret_failed ) ? ret_failed : ret_failed ? -( ret + 1 ) : ret;
                   -  + ]
    3633                 :             : }
    3634                 :             : 
    3635                 :             : 
    3636                 :             : /****************************************************************************/
    3637                 :         109 : int RemoveCalculatedNonStereo( CANON_GLOBALS *pCG,
    3638                 :             :                                sp_ATOM *at,
    3639                 :             :                                int num_atoms,
    3640                 :             :                                int num_at_tg,
    3641                 :             :                                AT_RANK **pRankStack1,
    3642                 :             :                                AT_RANK **pRankStack2,
    3643                 :             :                                AT_RANK *nTempRank,
    3644                 :             :                                NEIGH_LIST *NeighList,
    3645                 :             :                                const AT_RANK *nSymmRank,
    3646                 :             :                                AT_RANK *nCanonRank,
    3647                 :             :                                AT_RANK *nAtomNumberCanon,
    3648                 :             :                                CANON_STAT *pCS,
    3649                 :             :                                int vABParityUnknown )
    3650                 :             : {
    3651                 :         109 :     NEIGH_LIST *nl = NULL, *nl1 = NULL, *nl2 = NULL;
    3652                 :         109 :     AT_RANK    *nVisited1 = NULL, *nVisited2 = NULL, *nAtomNumberCanon1 = NULL, *nAtomNumberCanon2 = NULL;
    3653                 :         109 :     int        nNumRemoved = 0, nTotRemoved = 0, ret = 0, ret1 = 0, ret2 = 0;
    3654                 :             : 
    3655         [ -  + ]:         109 :     if (!AllocateForNonStereoRemoval( at, num_atoms, nSymmRank, nCanonRank,
    3656                 :             :         &nAtomNumberCanon1, &nAtomNumberCanon2,
    3657                 :             :         &nl, &nl1, &nl2, &nVisited1, &nVisited2 ))
    3658                 :             :     {
    3659                 :           0 :         return CT_OUT_OF_RAM;  /*   <BRKPT> */
    3660                 :             :     }
    3661                 :             : 
    3662                 :             :     do
    3663                 :             :     {
    3664                 :         109 :         nNumRemoved = 0;
    3665                 :             :         /*  bonds */
    3666                 :         109 :         ret = RemoveCalculatedNonStereoBondParities( pCG, at, num_atoms, num_at_tg,
    3667                 :             :                                               pRankStack1, pRankStack2, nTempRank, NeighList,
    3668                 :             :                                               nCanonRank, nSymmRank,
    3669                 :             :                                               nAtomNumberCanon, nAtomNumberCanon1, nAtomNumberCanon2,
    3670                 :             :                                               nl, nl1, nl2, nVisited1, nVisited2, pCS,
    3671                 :             :                                               vABParityUnknown );
    3672   [ +  -  -  + ]:         109 :         if (RETURNED_ERROR( ret ))
    3673                 :             :         {
    3674                 :           0 :             goto exit_function;
    3675                 :             :         }
    3676         [ -  + ]:         109 :         if (ret < 0)
    3677                 :             :         {
    3678         [ #  # ]:           0 :             if (ret < ret1)
    3679                 :             :             {  /*   <BRKPT> */
    3680                 :           0 :                 ret1 = ret;
    3681                 :             :             }
    3682                 :           0 :             ret = -( ret + 1 ); /*  number of removed */
    3683                 :             :         }
    3684                 :         109 :         nNumRemoved += ret;
    3685                 :             : 
    3686                 :             :         /*  centers */
    3687                 :         109 :         ret = RemoveCalculatedNonStereoCenterParities( pCG, at, num_atoms, num_at_tg,
    3688                 :             :                                               pRankStack1, pRankStack2, nTempRank, NeighList,
    3689                 :             :                                               nCanonRank, nSymmRank,
    3690                 :             :                                               nAtomNumberCanon, nAtomNumberCanon1, nAtomNumberCanon2,
    3691                 :             :                                               nl, nl1, nl2, nVisited1, nVisited2, pCS,
    3692                 :             :                                               vABParityUnknown );
    3693   [ +  -  -  + ]:         109 :         if (RETURNED_ERROR( ret ))
    3694                 :             :         {
    3695                 :           0 :             goto exit_function;
    3696                 :             :         }
    3697         [ -  + ]:         109 :         if (ret < 0)
    3698                 :             :         {
    3699         [ #  # ]:           0 :             if (ret < ret2)
    3700                 :             :             {  /*   <BRKPT> */
    3701                 :           0 :                 ret2 = ret;
    3702                 :             :             }
    3703                 :           0 :             ret = -( ret + 1 ); /*  number of removed */
    3704                 :             :         }
    3705                 :         109 :         nNumRemoved += ret;
    3706                 :             : 
    3707                 :         109 :         nTotRemoved += nNumRemoved;
    3708                 :             :     }
    3709         [ -  + ]:         109 :     while (nNumRemoved);
    3710                 :             : 
    3711   [ +  -  -  +  :         109 :     if (!RETURNED_ERROR( ret1 ) && !RETURNED_ERROR( ret2 ))
             +  -  -  + ]
    3712                 :             :     {
    3713                 :         109 :         ret = inchi_min( ret1, ret2 );
    3714                 :         109 :         ret = ( ret >= 0 ) ? nTotRemoved : -( 1 + nTotRemoved );
    3715                 :             :     }
    3716                 :             : 
    3717                 :           0 : exit_function:
    3718                 :             : 
    3719                 :         109 :     DeAllocateForNonStereoRemoval( &nAtomNumberCanon1, &nAtomNumberCanon2, &nl, &nl1, &nl2, &nVisited1, &nVisited2 );
    3720                 :             : 
    3721                 :         109 :     return ret;
    3722                 :             : }
    3723                 :             : 
    3724                 :             : #endif /* } REMOVE_CALC_NONSTEREO */
        

Generated by: LCOV version 2.0-1