LCOV - code coverage report
Current view: top level - src - ichimap2.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 19.0 % 1209 230
Test Date: 2026-05-04 07:05:02 Functions: 56.7 % 30 17
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 10.3 % 1288 133

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

Generated by: LCOV version 2.0-1