LCOV - code coverage report
Current view: top level - src - ichimap1.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 20.2 % 411 83
Test Date: 2026-10-14 12:14:55 Functions: 40.7 % 27 11
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 12.8 % 383 49

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * SPDX-License-Identifier: MIT
       3                 :             :  * Copyright (c) 2024 IUPAC and InChI Trust
       4                 :             :  */
       5                 :             : 
       6                 :             : #include <string.h>
       7                 :             : 
       8                 :             : #include "mode.h"
       9                 :             : #include "ichicomn.h"
      10                 :             : 
      11                 :             : #include "bcf_s.h"
      12                 :             : 
      13                 :             : /****************************************************************************
      14                 :             :   Check if all equivalent to cr1 possibly stereogenic atoms:
      15                 :             :   1) have KNOWN parity, and
      16                 :             :   2) their parities are same
      17                 :             : ****************************************************************************/
      18                 :           0 : int All_SC_Same( AT_RANK canon_rank1, /*  canonical number */
      19                 :             :                   const ppAT_RANK pRankStack1,
      20                 :             :                   const ppAT_RANK pRankStack2,
      21                 :             :                   const AT_RANK *nAtomNumberCanonFrom,
      22                 :             :                   const sp_ATOM *at )
      23                 :             : {
      24                 :           0 :     int     n1 = (int) nAtomNumberCanonFrom[(int) canon_rank1 - 1];
      25                 :           0 :     AT_RANK r1 = pRankStack1[0][n1];
      26                 :           0 :     int     iMax1 = (int) r1;
      27                 :             :     int     i1, s1;
      28                 :           0 :     int     bFound = 0, stereo_atom_parity = -1;
      29                 :             : 
      30                 :             :     /*  find one stereo atom such that canon_rank1 can be mapped on it */
      31   [ #  #  #  # ]:           0 :     for (i1 = 1; i1 <= iMax1 && r1 == pRankStack2[0][s1 = (int) pRankStack2[1][iMax1 - i1]]; i1++)
      32                 :             :     {
      33         [ #  # ]:           0 :         if (at[s1].stereo_bond_neighbor[0])
      34                 :             :         {
      35                 :           0 :             bFound = 0; /* at[s1] is not sp3-stereogenic: it belongs to a stereobond */
      36                 :           0 :             break;
      37                 :             :         }
      38                 :             :         else
      39         [ #  # ]:           0 :             if (i1 == 1)
      40                 :             :             {
      41                 :           0 :                 stereo_atom_parity = PARITY_VAL( at[s1].stereo_atom_parity );
      42   [ #  #  #  # ]:           0 :                 if (!ATOM_PARITY_KNOWN( stereo_atom_parity ))
      43                 :             :                 {
      44                 :           0 :                     bFound = 0;  /* at[s1] does not have a KNOWN parity */
      45                 :           0 :                     break;
      46                 :             :                 }
      47                 :             :             }
      48                 :             :             else
      49         [ #  # ]:           0 :                 if (stereo_atom_parity != PARITY_VAL( at[s1].stereo_atom_parity ))
      50                 :             :                 {
      51                 :           0 :                     bFound = 0; /* two equivalent atoms have different parities */
      52                 :           0 :                     break;
      53                 :             :                 }
      54                 :           0 :         bFound++;
      55                 :             :     }
      56                 :             : 
      57                 :           0 :     return bFound;
      58                 :             : }
      59                 :             : 
      60                 :             : 
      61                 :             : /****************************************************************************
      62                 :             :   get next available (not mapped yet) rank for a stereo center atom
      63                 :             : ****************************************************************************/
      64                 :         367 : int Next_SC_At_CanonRank2( AT_RANK *canon_rank1,        /*  1st call input: largest canon number mapped so far or 0 */
      65                 :             :                                                         /*  output: suggested canon. rank > than input if success */
      66                 :             :                            AT_RANK *canon_rank1_min,    /*  1st call:0 next calls: first tried canon. number */
      67                 :             :                            int *bFirstTime,             /*  1 at the time of the 1st call  */
      68                 :             :                            S_CHAR *bAtomUsedForStereo,  /*  STEREO_AT_MARK if the atom has not been mapped yet */
      69                 :             :                            const ppAT_RANK pRankStack1, /*  mapping ranks/sort order of atoms with canon. numbers (from) */
      70                 :             :                            const ppAT_RANK pRankStack2, /*  mapping ranks/sort order of atoms with stereo (to) */
      71                 :             :                            const AT_RANK *nAtomNumberCanonFrom, /*  sorted order of the canon. numbers */
      72                 :             :                            int num_atoms )
      73                 :             : {
      74                 :         367 :     AT_RANK canon_rank1_inp = *canon_rank1;
      75                 :             :     AT_RANK cr1;  /*  canonical rank (canonical number) */
      76                 :             :     AT_RANK r1;   /*  mapping rank */
      77                 :             :     int     n1;   /*  ord. number of an atom with the canon. number */
      78                 :             :     int     s1;   /*  ord. number of an atom with stereo */
      79                 :         367 :     int     i1, bFound = 0;
      80                 :             :     int     iMax1;
      81                 :             : 
      82         [ -  + ]:         367 :     if (canon_rank1_inp < *canon_rank1_min)
      83                 :             :     {
      84                 :           0 :         canon_rank1_inp = *canon_rank1_min;
      85                 :             :     }
      86                 :             :     else
      87                 :             :     {
      88         [ +  + ]:         367 :         if (canon_rank1_inp < 1)
      89                 :             :         {
      90                 :         106 :             canon_rank1_inp = 1;
      91                 :             :         }
      92                 :             :         else
      93                 :             :         {
      94                 :         261 :             canon_rank1_inp++; /*  next canonical rank */
      95                 :             :         }
      96                 :             :     }
      97                 :         367 :     cr1 = canon_rank1_inp;
      98                 :             : 
      99         [ +  - ]:         733 :     while ((int) cr1 <= num_atoms)
     100                 :             :     {
     101                 :         733 :         n1 = (int) nAtomNumberCanonFrom[(int) cr1 - 1]; /*  atom1 (which has canon. rank cr1) ord. number */
     102                 :         733 :         iMax1 = (int) ( r1 = pRankStack1[0][n1] ); /*  mapping rank of atom1 */
     103                 :             :         /*  find atoms "to" to which the canon. number can be mapped; they have mapping rank r1, number s1 */
     104   [ +  +  +  + ]:        1165 :         for (i1 = 1; i1 <= iMax1 && r1 == pRankStack2[0][s1 = (int) pRankStack2[1][iMax1 - i1]]; i1++)
     105                 :             :         {
     106                 :             :             /*  looking for a stereo center atom that has mapping rank r1 */
     107         [ +  + ]:         799 :             if (bAtomUsedForStereo[s1] == STEREO_AT_MARK)
     108                 :             :             {
     109                 :             :                 /*  found a sterogenic atom that has not been mapped yet */
     110                 :         367 :                 bFound = 1;
     111                 :         367 :                 break;
     112                 :             :             }
     113                 :             :         }
     114         [ +  + ]:         733 :         if (bFound)
     115                 :             :         {
     116                 :             :             /*  one sterogenic not mapped yet atom "to" has been found */
     117         [ +  - ]:         367 :             if (*bFirstTime)
     118                 :             :             {
     119                 :         367 :                 *canon_rank1_min = cr1;
     120                 :         367 :                 *bFirstTime = 0;
     121                 :             :             }
     122                 :         367 :             break;
     123                 :             :         }
     124                 :             :         else
     125                 :             :         {
     126                 :             :              /*  a not mapped yet stereogenic atom has not found */
     127                 :             :              /*  for the mapping rank r1 defined by the canonical rank cr1; try next cr1 */
     128                 :         366 :             cr1++;
     129                 :             :         }
     130                 :             :     }
     131         [ +  - ]:         367 :     if (bFound)
     132                 :             :     {
     133                 :             :         /*  success */
     134                 :         367 :         *canon_rank1 = cr1;
     135                 :         367 :         return 1;
     136                 :             :     }
     137                 :             : 
     138                 :           0 :     return 0;
     139                 :             : }
     140                 :             : 
     141                 :             : 
     142                 :             : /****************************************************************************/
     143                 :          51 : int CompareLinCtStereoDble( AT_STEREO_DBLE *LinearCTStereoDble1,
     144                 :             :                             int nLenLinearCTStereoDble1,
     145                 :             :                             AT_STEREO_DBLE *LinearCTStereoDble2,
     146                 :             :                             int nLenLinearCTStereoDble2 )
     147                 :             : {
     148                 :          51 :     int i, num, ret = 0;
     149                 :             : 
     150                 :             :     /* compare double bonds */
     151   [ -  +  -  - ]:          51 :     if (LinearCTStereoDble1 && LinearCTStereoDble2)
     152                 :             :     {
     153                 :           0 :         num = inchi_min( nLenLinearCTStereoDble1, nLenLinearCTStereoDble2 );
     154         [ #  # ]:           0 :         for (i = 0; i < num; i++)
     155                 :             :         {
     156         [ #  # ]:           0 :             if ((ret = (int) LinearCTStereoDble1[i].at_num1 - (int) LinearCTStereoDble2[i].at_num1)) /* djb-rwth: addressing LLVM warning */
     157                 :           0 :                 break;
     158         [ #  # ]:           0 :             if ((ret = (int) LinearCTStereoDble1[i].at_num2 - (int) LinearCTStereoDble2[i].at_num2)) /* djb-rwth: addressing LLVM warning */
     159                 :           0 :                 break;
     160         [ #  # ]:           0 :             if ((ret = (int) LinearCTStereoDble1[i].parity - (int) LinearCTStereoDble2[i].parity)) /* djb-rwth: addressing LLVM warning */
     161                 :           0 :                 break;
     162                 :             :         }
     163         [ #  # ]:           0 :         if (!ret)
     164                 :             :         {
     165                 :           0 :             ret = nLenLinearCTStereoDble1 - nLenLinearCTStereoDble2;
     166                 :             :         }
     167                 :             :     }
     168                 :             :     else
     169                 :             :     {
     170   [ -  +  -  - ]:          51 :         if (LinearCTStereoDble1 && nLenLinearCTStereoDble1 > 0)
     171                 :             :         {
     172                 :           0 :             ret = 1;
     173                 :             :         }
     174                 :             :         else
     175                 :             :         {
     176   [ -  +  -  - ]:          51 :             if (LinearCTStereoDble2 && nLenLinearCTStereoDble2 > 0)
     177                 :             :             {
     178                 :           0 :                 ret = -1;
     179                 :             :             }
     180                 :             :         }
     181                 :             :     }
     182                 :             : 
     183                 :          51 :     return ret;
     184                 :             : }
     185                 :             : 
     186                 :             : 
     187                 :             : /****************************************************************************/
     188                 :          51 : int CompareLinCtStereoCarb( AT_STEREO_CARB *LinearCTStereoCarb1,
     189                 :             :                             int nLenLinearCTStereoCarb1,
     190                 :             :                             AT_STEREO_CARB *LinearCTStereoCarb2,
     191                 :             :                             int nLenLinearCTStereoCarb2 )
     192                 :             : {
     193                 :          51 :     int i, num, ret = 0;
     194                 :             : 
     195                 :             :     /* compare stereocenters */
     196   [ +  -  +  - ]:          51 :     if (LinearCTStereoCarb1 && LinearCTStereoCarb2)
     197                 :             :     {
     198                 :          51 :         num = inchi_min( nLenLinearCTStereoCarb1, nLenLinearCTStereoCarb2 );
     199         [ +  - ]:          53 :         for (i = 0; i < num; i++)
     200                 :             :         {
     201         [ -  + ]:          53 :             if ((ret = (int) LinearCTStereoCarb1[i].at_num - (int) LinearCTStereoCarb2[i].at_num)) /* djb-rwth: addressing LLVM warning */
     202                 :           0 :                 break;
     203         [ +  + ]:          53 :             if ((ret = (int) LinearCTStereoCarb1[i].parity - (int) LinearCTStereoCarb2[i].parity)) /* djb-rwth: addressing LLVM warning */
     204                 :          51 :                 break;
     205                 :             :         }
     206         [ -  + ]:          51 :         if (!ret)
     207                 :             :         {
     208                 :           0 :             ret = nLenLinearCTStereoCarb1 - nLenLinearCTStereoCarb2;
     209                 :             :         }
     210                 :             :     }
     211                 :             :     else
     212   [ #  #  #  # ]:           0 :         if (LinearCTStereoCarb1 && nLenLinearCTStereoCarb1 > 0)
     213                 :             :         {
     214                 :           0 :             ret = 1;
     215                 :             :         }
     216                 :             :         else
     217   [ #  #  #  # ]:           0 :             if (LinearCTStereoCarb2 && nLenLinearCTStereoCarb2 > 0)
     218                 :             :             {
     219                 :           0 :                 ret = -1;
     220                 :             :             }
     221                 :             : 
     222                 :          51 :     return ret;
     223                 :             : }
     224                 :             : 
     225                 :             : 
     226                 :             : /****************************************************************************/
     227                 :          51 : int CompareLinCtStereo( AT_STEREO_DBLE *LinearCTStereoDble1,
     228                 :             :                         int nLenLinearCTStereoDble1,
     229                 :             :                         AT_STEREO_CARB *LinearCTStereoCarb1,
     230                 :             :                         int nLenLinearCTStereoCarb1,
     231                 :             :                         AT_STEREO_DBLE *LinearCTStereoDble2,
     232                 :             :                         int nLenLinearCTStereoDble2,
     233                 :             :                         AT_STEREO_CARB *LinearCTStereoCarb2,
     234                 :             :                         int nLenLinearCTStereoCarb2 )
     235                 :             : {
     236                 :             :     int ret;
     237                 :             : 
     238                 :             :     /* compare double bonds */
     239                 :          51 :     ret = CompareLinCtStereoDble( LinearCTStereoDble1, nLenLinearCTStereoDble1,
     240                 :             :                                    LinearCTStereoDble2, nLenLinearCTStereoDble2 );
     241         [ +  - ]:          51 :     if (!ret)
     242                 :             :     {
     243                 :          51 :         ret = CompareLinCtStereoCarb( LinearCTStereoCarb1, nLenLinearCTStereoCarb1,
     244                 :             : 
     245                 :             :                                       LinearCTStereoCarb2, nLenLinearCTStereoCarb2 );
     246                 :             :     }
     247                 :          51 :     return ret;
     248                 :             : }
     249                 :             : 
     250                 :             : 
     251                 :             : /****************************************************************************/
     252                 :         653 : int CompareLinCtStereoAtomToValues( AT_STEREO_CARB *LinearCTStereoCarb,
     253                 :             :                                     AT_RANK at_rank_canon1,
     254                 :             :                                     U_CHAR parity )
     255                 :             : {
     256         [ -  + ]:         653 :     if (LinearCTStereoCarb->at_num CT_GREATER_THAN at_rank_canon1)
     257                 :             :     {
     258                 :           0 :         return 1;
     259                 :             :     }
     260         [ -  + ]:         653 :     if (LinearCTStereoCarb->at_num != at_rank_canon1)
     261                 :             :     {
     262                 :           0 :         return -1;
     263                 :             :     }
     264         [ +  + ]:         653 :     if (LinearCTStereoCarb->parity CT_GREATER_THAN parity)
     265                 :             :     {
     266                 :         117 :         return 1;
     267                 :             :     }
     268         [ -  + ]:         536 :     if (LinearCTStereoCarb->parity != parity)
     269                 :             :     {
     270                 :           0 :         return -1;
     271                 :             :     }
     272                 :             : 
     273                 :         536 :     return 0;
     274                 :             : }
     275                 :             : 
     276                 :             : 
     277                 :             : /****************************************************************************
     278                 :             :   Find atom number from the mapping rank and return 1, or
     279                 :             :   if the mapping rank is tied and the atom number is not unique then return 0
     280                 :             : ****************************************************************************/
     281                 :           0 : int bUniqueAtNbrFromMappingRank( AT_RANK **pRankStack, AT_RANK nAtRank, AT_NUMB *nAtNumber )
     282                 :             : {
     283                 :           0 :     int       r = (int) nAtRank - 1;
     284                 :           0 :     AT_NUMB   i = pRankStack[1][r];
     285   [ #  #  #  # ]:           0 :     if (nAtRank == pRankStack[0][(int) i] &&
     286         [ #  # ]:           0 :         ( !r || nAtRank != pRankStack[0][pRankStack[1][r - 1]] )
     287                 :             :        )
     288                 :             :     {
     289                 :           0 :         *nAtNumber = i;
     290                 :           0 :         return 1;
     291                 :             :     }
     292                 :             : 
     293                 :           0 :     return 0;
     294                 :             : }
     295                 :             : 
     296                 :             : 
     297                 :             : /****************************************************************************
     298                 :             :   Get minimal set (class) representative and partially compress the partitioning
     299                 :             :   mcr = minimal class representative.
     300                 :             : ****************************************************************************/
     301                 :           0 : AT_RANK nGetMcr( AT_RANK *nEqArray, AT_RANK n )
     302                 :             : {
     303                 :             :     AT_RANK n1, n2, mcr; /*  recursive version is much shorter. */
     304                 :             : 
     305                 :           0 :     n1 = nEqArray[(int) n];
     306         [ #  # ]:           0 :     if (n == n1)
     307                 :             :     {
     308                 :           0 :         return n;
     309                 :             :     }
     310                 :             :     /*  1st pass: find mcr */
     311         [ #  # ]:           0 :     while (n1 != ( n2 = nEqArray[(int) n1] ))
     312                 :             :     {
     313                 :           0 :         n1 = n2;
     314                 :             :     }
     315                 :             :     /*  2nd pass: copy mcr to each element of the set starting from nEqArray[n] */
     316                 :           0 :     mcr = n1;
     317                 :           0 :     n1 = n;
     318         [ #  # ]:           0 :     while ( /*n1*/ mcr != ( n2 = nEqArray[(int) n1] ))
     319                 :             :     {
     320                 :           0 :         nEqArray[(int) n1] = mcr;
     321                 :           0 :         n1 = n2;
     322                 :             :     }
     323                 :             : 
     324                 :           0 :     return ( mcr );
     325                 :             : }
     326                 :             : 
     327                 :             : 
     328                 :             : /****************************************************************************
     329                 :             :   Join 2 sets (classes) that have members n1 and n2
     330                 :             : ****************************************************************************/
     331                 :           0 : int nJoin2Mcrs( AT_RANK *nEqArray, AT_RANK n1, AT_RANK n2 )
     332                 :             : {
     333                 :           0 :     n1 = nGetMcr( nEqArray, n1 );
     334                 :           0 :     n2 = nGetMcr( nEqArray, n2 );
     335         [ #  # ]:           0 :     if (n1 < n2)
     336                 :             :     {
     337                 :           0 :         nEqArray[n2] = n1;
     338                 :           0 :         return 1; /*  a change has been made */
     339                 :             :     }
     340         [ #  # ]:           0 :     if (n2 < n1)
     341                 :             :     {
     342                 :           0 :         nEqArray[n1] = n2;
     343                 :           0 :         return 1; /*  a change has been made */
     344                 :             :     }
     345                 :             : 
     346                 :           0 :     return 0; /*  no changes */
     347                 :             : }
     348                 :             : 
     349                 :             : /*********************************************************************************
     350                 :             :  *  For all pairs of atoms that are:                                             *
     351                 :             :  *  (a) connected by a possibly stereogenic bond                                 *
     352                 :             :  *  (b) "equivalent" at this point to canon_rank1-canon_rank2 :                  *
     353                 :             :  *  Check if they:                                                               *
     354                 :             :  *  1) are connected by a stereo bond or cumulene bonds of the same length       *
     355                 :             :  *  2) have KNOWN parity, and                                                    *
     356                 :             :  *  3) their parities are same                                                   *
     357                 :             :  *********************************************************************************/
     358                 :           0 : int All_SB_Same( AT_RANK canon_rank1,
     359                 :             :                  AT_RANK canon_rank2, /*  canonical numbers */
     360                 :             :                  const ppAT_RANK pRankStack1,
     361                 :             :                  const ppAT_RANK pRankStack2,
     362                 :             :                  const AT_RANK *nAtomNumberCanonFrom,
     363                 :             :                  sp_ATOM *at )
     364                 :             : {
     365                 :           0 :     int     n1 = (int) nAtomNumberCanonFrom[(int) canon_rank1 - 1]; /* at1 has canon_rank1 */
     366                 :           0 :     int     n2 = (int) nAtomNumberCanonFrom[(int) canon_rank2 - 1]; /* at2 has canon_rank2 */
     367                 :           0 :     AT_RANK r1 = pRankStack1[0][n1]; /* at1 mapping rank */
     368                 :           0 :     AT_RANK r2 = pRankStack1[0][n2]; /* at2 mapping rank */
     369                 :             :     AT_RANK rNeigh1, rNeigh2;
     370                 :           0 :     int     iMax1 = (int) r1;
     371                 :             :     /* int     iMax2 = (int)r2; */
     372                 :           0 :     int     i1, i2, s1 = 0, s2 = 0, k1 = 0, k2, m, k, num_equal;
     373                 :           0 :     int     bNotFound = 1, cumulene_len, stereo_bond_parity;
     374                 :             : 
     375                 :             :     /*  at the first atom that possibly may have canon_rank1 find one stereo bond such that */
     376                 :             :     /*  canon_rank1-canon_rank2 possibly may be mapped on it */
     377   [ #  #  #  # ]:           0 :     for (i1 = 1; i1 <= iMax1 && r1 == pRankStack2[0][s1 = (int) pRankStack2[1][iMax1 - i1]]; i1++)
     378                 :             :     {
     379                 :             :         /* at[n1] may be possible to map on at[s1] */
     380                 :           0 :         for (k1 = 0, s2 = 0, bNotFound = 1;
     381   [ #  #  #  # ]:           0 :               k1 < MAX_NUM_STEREO_BONDS && ( s2 = (int) at[s1].stereo_bond_neighbor[k1] ) &&
     382         [ #  # ]:           0 :               ( bNotFound = ( r2 != pRankStack2[0][--s2] ) ); k1++)
     383                 :             :             ; /* continue until the 1st at[s2] (to which at[n2] may be mapped) have been found */
     384         [ #  # ]:           0 :         if (!bNotFound)
     385                 :             :         {
     386                 :           0 :             break; /* stop at 1st found */
     387                 :             :         }
     388                 :             :     }
     389         [ #  # ]:           0 :     if (bNotFound)
     390                 :             :     {
     391                 :           0 :         return -1; /*  error: no mapping exists */
     392                 :             :     }
     393   [ #  #  #  #  :           0 :     for (k2 = 0, m = 0; k2 < MAX_NUM_STEREO_BONDS && ( m = (int) at[s2].stereo_bond_neighbor[k2] ) && m - 1 != s1; k2++)
                   #  # ]
     394                 :             :         ;
     395         [ #  # ]:           0 :     if (m - 1 != s1)
     396                 :             :     {
     397                 :           0 :         return -1; /*  program error: stereo bond in opposite direction not found */
     398                 :             :     }
     399                 :           0 :     stereo_bond_parity = at[s1].stereo_bond_parity[k1];
     400   [ #  #  #  # ]:           0 :     if (!PARITY_KNOWN( stereo_bond_parity ))
     401                 :             :     {
     402                 :           0 :         return 0;
     403                 :             :     }
     404                 :           0 :     cumulene_len = BOND_CHAIN_LEN( stereo_bond_parity );
     405                 :           0 :     rNeigh1 = pRankStack2[0][(int) at[s1].neighbor[(int) at[s1].stereo_bond_ord[k1]]];
     406                 :           0 :     rNeigh2 = pRankStack2[0][(int) at[s2].neighbor[(int) at[s2].stereo_bond_ord[k2]]];
     407                 :             : 
     408                 :           0 :     num_equal = 0;
     409                 :             :     /*  Search among ALL neighbors because sometimes a stereo bond may be mapped on a non-stereo bond. */
     410                 :             :     /*  If is so then return 0: not all mappings are stereo-equivalent */
     411   [ #  #  #  # ]:           0 :     for (s1 = 1; s1 <= iMax1 && r1 == pRankStack2[0][i1 = (int) pRankStack2[1][iMax1 - s1]]; s1++)
     412                 :             :     {
     413         [ #  # ]:           0 :         for (k = 0; k < at[i1].valence; k++)
     414                 :             :         {
     415                 :           0 :             n1 = at[i1].neighbor[k];
     416         [ #  # ]:           0 :             if (rNeigh1 != pRankStack2[0][n1])
     417                 :             :             {
     418                 :           0 :                 continue; /*  wrong neighbor */
     419                 :             :             }
     420         [ #  # ]:           0 :             if (cumulene_len)
     421                 :             :             {
     422                 :             :                 int prev, next, len, j;
     423         [ #  # ]:           0 :                 for (prev = i1, len = 0, next = n1; len < cumulene_len; len++)
     424                 :             :                 {
     425   [ #  #  #  # ]:           0 :                     if (at[next].valence == 2 && !at[next].num_H)
     426                 :             :                     {
     427                 :           0 :                         j = ( (int) at[next].neighbor[0] == prev );
     428                 :           0 :                         prev = next;
     429                 :           0 :                         next = at[next].neighbor[j];
     430                 :             :                     }
     431                 :             :                     else
     432                 :             :                     {
     433                 :             :                         break; /*  cannot continue */
     434                 :             :                     }
     435                 :             :                 }
     436         [ #  # ]:           0 :                 if (len != cumulene_len ||
     437         [ #  # ]:           0 :                      r2 != pRankStack2[0][next] ||
     438         [ #  # ]:           0 :                      rNeigh2 != pRankStack2[0][prev])
     439                 :             :                 {
     440                 :             :                     /*  cumulene chain not found */
     441                 :           0 :                     continue;
     442                 :             :                 }
     443                 :           0 :                 i2 = next;
     444                 :             :             }
     445                 :             :             else
     446                 :             :             {
     447                 :           0 :                 i2 = n1;
     448                 :             :             }
     449                 :             :             /*  find if a stereogenic bond between at[i1]-at[i2] exists */
     450                 :           0 :             for (k1 = 0; k1 < MAX_NUM_STEREO_BONDS &&
     451   [ #  #  #  #  :           0 :                 ( m = (int) at[i1].stereo_bond_neighbor[k1] ) && m - 1 != i2; k1++)
                   #  # ]
     452                 :             :                 ;
     453         [ #  # ]:           0 :             if (m - 1 != i2)
     454                 :             :             {
     455                 :           0 :                 return 0;
     456                 :             :             }
     457                 :           0 :             for (k2 = 0; k2 < MAX_NUM_STEREO_BONDS &&
     458   [ #  #  #  #  :           0 :                 ( m = (int) at[i2].stereo_bond_neighbor[k2] ) && m - 1 != i1; k2++)
                   #  # ]
     459                 :             :                 ;
     460         [ #  # ]:           0 :             if (m - 1 != i1)
     461                 :             :             {
     462                 :           0 :                 return 0;
     463                 :             :             }
     464         [ #  # ]:           0 :             if (at[i1].stereo_bond_parity[k1] != at[i2].stereo_bond_parity[k2])
     465                 :             :             {
     466                 :           0 :                 return -1; /*  program error */
     467                 :             :             }
     468         [ #  # ]:           0 :             if (stereo_bond_parity != at[i1].stereo_bond_parity[k1])
     469                 :             :             {
     470                 :           0 :                 return 0;
     471                 :             :             }
     472                 :           0 :             num_equal++;
     473                 :             :         }
     474                 :             :     }
     475                 :             : 
     476                 :           0 :     return num_equal;
     477                 :             : }
     478                 :             : 
     479                 :             : 
     480                 :             : /****************************************************************************
     481                 :             :   get min. ranks for the stereo bond atoms
     482                 :             : ****************************************************************************/
     483                 :           0 : int Next_SB_At_CanonRanks2( AT_RANK *canon_rank1,
     484                 :             :                             AT_RANK *canon_rank2, /*  canonical numbers */
     485                 :             :                             AT_RANK *canon_rank1_min,
     486                 :             :                             AT_RANK *canon_rank2_min,
     487                 :             :                             int *bFirstTime,
     488                 :             :                             S_CHAR *bAtomUsedForStereo,
     489                 :             :                             const ppAT_RANK pRankStack1,
     490                 :             :                             const ppAT_RANK pRankStack2,
     491                 :             :                             const AT_RANK *nCanonRankFrom,
     492                 :             :                             const AT_RANK *nAtomNumberCanonFrom,
     493                 :             :                             const sp_ATOM *at,
     494                 :             :                             int num_atoms,
     495                 :             :                             int bAllene )
     496                 :             : {
     497                 :           0 :     AT_RANK canon_rank1_inp = *canon_rank1;
     498                 :           0 :     AT_RANK canon_rank2_inp = *canon_rank2;
     499                 :             :     AT_RANK cr1, cr2; /*  canonical ranks (canonical numbers) */
     500                 :             :     AT_RANK r1, r2;   /*  mapping ranks */
     501                 :             :     int     n1, n2;   /*  ord. numbers of atoms with stereo */
     502                 :             :     int     s1, s2;   /*  ord. numbers of atoms with canon. numbers */
     503                 :             :     int     i1, i2, k, m;
     504                 :             :     int     iMax1, iMax2;
     505                 :             : 
     506         [ #  # ]:           0 :     if (canon_rank1_inp < *canon_rank1_min ||
     507         [ #  # ]:           0 :          (canon_rank1_inp == *canon_rank1_min &&
     508         [ #  # ]:           0 :          canon_rank2_inp < *canon_rank2_min)) /* djb-rwth: addressing LLVM warning */
     509                 :             :     {
     510                 :             : 
     511                 :           0 :         canon_rank1_inp = *canon_rank1_min;
     512                 :           0 :         canon_rank2_inp = *canon_rank2_min;
     513                 :             :     }
     514                 :             :     else
     515         [ #  # ]:           0 :         if (canon_rank1_inp < 2)
     516                 :             :         {
     517                 :           0 :             canon_rank1_inp = 2;
     518                 :           0 :             canon_rank2_inp = 0;
     519                 :             :         }
     520                 :           0 :     cr1 = canon_rank1_inp;
     521                 :           0 :     cr2 = num_atoms; /* initialize. 1/8/2002 */
     522         [ #  # ]:           0 :     while ((int) cr1 <= num_atoms)
     523                 :             :     {
     524                 :           0 :         cr2 = cr1;
     525                 :           0 :         n1 = (int) nAtomNumberCanonFrom[(int) cr1 - 1]; /*  atom1=at[n1] (which has canon. rank) ord. number */
     526                 :           0 :         iMax1 = (int) ( r1 = pRankStack1[0][n1] ); /*  mapping rank of atom1 */
     527   [ #  #  #  # ]:           0 :         for (i1 = 1; i1 <= iMax1 && r1 == pRankStack2[0][s1 = (int) pRankStack2[1][iMax1 - i1]]; i1++)
     528                 :             :         {
     529                 :             :             /*  looking for a stereo bond atom that has mapping rank r1 */
     530                 :             :             /*  found at[s1] such that rank cr1 can be mapped on at[s1] because cr1 and s1 have equal */
     531                 :             :             /*  mapping rank = r1. Check at[s1] stereo bonds */
     532   [ #  #  #  # ]:           0 :             if (bAtomUsedForStereo[s1] && bAtomUsedForStereo[s1] < STEREO_AT_MARK)
     533                 :             :             {
     534   [ #  #  #  # ]:           0 :                 for (k = 0; k < MAX_NUM_STEREO_BONDS && ( s2 = (int) at[s1].stereo_bond_neighbor[k] ); k++) /* djb-rwth: removing redundant code */
     535                 :             :                 {
     536                 :             :                     /*  stereo bond at[s1]-at[s2] has been found */
     537         [ #  # ]:           0 :                     if (bAtomUsedForStereo[--s2])
     538                 :             :                     {
     539                 :             :                         /*  stereo bonds have not been mapped. however, this check is not needed */
     540                 :           0 :                         int cumulene_len = BOND_CHAIN_LEN( at[s1].stereo_bond_parity[k] );
     541   [ #  #  #  # ]:           0 :                         if ((cumulene_len % 2 && !bAllene) || /* 09-26-2003 */
     542   [ #  #  #  # ]:           0 :                              (!( cumulene_len % 2 ) && bAllene)) /* djb-rwth: addressing LLVM warning */
     543                 :             :                         { /* 08-17-2003 Fix05 */
     544                 :           0 :                             continue;
     545                 :             :                         }
     546                 :           0 :                         iMax2 = (int) ( r2 = pRankStack2[0][s2] ); /*  mapping rank of atom2 */
     547                 :             :                         /*  Go back to canonical ranks and find an atom that has mapping rank r2 */
     548                 :             :                         /*  and is connected to the atom with canonical rank cr1 (possibly by cumulene chain) */
     549                 :             :                         /*  These cr1-cr2 canon. ranks possibly can be mapped on at[s1]-at[s2] stereo bond */
     550   [ #  #  #  # ]:           0 :                         for (i2 = 1; i2 <= iMax2 && r2 == pRankStack1[0][n2 = (int) pRankStack1[1][iMax2 - i2]]; i2++)
     551                 :             :                         {
     552         [ #  # ]:           0 :                             if (cumulene_len)
     553                 :             :                             {
     554                 :             :                                 int prev, next, len, j;
     555         [ #  # ]:           0 :                                 for (m = 0; m < at[n1].valence; m++)
     556                 :             :                                 {
     557         [ #  # ]:           0 :                                     for (prev = n1, len = 0, next = (int) at[n1].neighbor[m]; len < cumulene_len; len++)
     558                 :             :                                     {
     559   [ #  #  #  # ]:           0 :                                         if (at[next].valence == 2 && !at[next].num_H)
     560                 :             :                                         {
     561                 :           0 :                                             j = ( (int) at[next].neighbor[0] == prev );
     562                 :           0 :                                             prev = next;
     563                 :           0 :                                             next = at[next].neighbor[j];
     564                 :             :                                         }
     565                 :             :                                         else
     566                 :             :                                         {
     567                 :             :                                             break; /*  cannot continue */
     568                 :             :                                         }
     569                 :             :                                     }
     570   [ #  #  #  # ]:           0 :                                     if (len == cumulene_len && n2 == next)
     571                 :             :                                     {
     572                 :           0 :                                         break;
     573                 :             :                                     }
     574                 :             :                                 }
     575                 :             :                             }
     576                 :             :                             else
     577                 :             :                             {
     578   [ #  #  #  # ]:           0 :                                 for (m = 0; m < at[n1].valence && n2 != (int) at[n1].neighbor[m]; m++)
     579                 :             :                                     ;
     580                 :             :                             }
     581         [ #  # ]:           0 :                             if (m < at[n1].valence &&
     582         [ #  # ]:           0 :                                  nCanonRankFrom[n2] < cr2 &&
     583         [ #  # ]:           0 :                                  nCanonRankFrom[n2] > canon_rank2_inp)
     584                 :             :                             {
     585                 :             : 
     586                 :           0 :                                 cr2 = nCanonRankFrom[n2]; /*  found a candidate for cr2 */
     587                 :             :                             }
     588                 :             :                         }
     589                 :             :                     }
     590                 :             :                 }
     591                 :             :             }
     592                 :             :         }
     593         [ #  # ]:           0 :         if (cr2 >= cr1)
     594                 :             :         {
     595                 :             :             /*  not found for this r1 */
     596                 :           0 :             cr1++;
     597                 :           0 :             canon_rank2_inp = 0;
     598                 :             :         }
     599                 :             :         else
     600                 :             :         {
     601                 :             :              /* found cr2 < cr1 */
     602         [ #  # ]:           0 :             if (*bFirstTime)
     603                 :             :             {
     604                 :           0 :                 *canon_rank1_min = cr1;
     605                 :           0 :                 *canon_rank2_min = cr2;
     606                 :           0 :                 *bFirstTime = 0;
     607                 :             :             }
     608                 :           0 :             break;
     609                 :             :         }
     610                 :             :     }
     611   [ #  #  #  # ]:           0 :     if (cr1 > cr2 && cr1 <= num_atoms)
     612                 :             :     {
     613                 :             :         /*  success */
     614                 :           0 :         *canon_rank1 = cr1;
     615                 :           0 :         *canon_rank2 = cr2;
     616                 :           0 :         return 1;
     617                 :             :     }
     618                 :             : 
     619                 :           0 :     return 0;
     620                 :             : }
     621                 :             : 
     622                 :             : 
     623                 :             : /****************************************************************************/
     624                 :           0 : int NextStereoParity2Test( int *stereo_bond_parity,
     625                 :             :                            int *sb_parity_calc,
     626                 :             :                            int nNumBest,
     627                 :             :                            int nNumWorse,
     628                 :             :                            int nNumUnkn,
     629                 :             :                            int nNumUndf,
     630                 :             :                            int nNumCalc,
     631                 :             :                            int vABParityUnknown )
     632                 :             : {
     633                 :             :     /* sequence of (stereo_bond_parity, sb_parity_calc) pairs:
     634                 :             : 
     635                 :             :           (BEST_PARITY, BEST_PARITY)  <calc>
     636                 :             :                       |
     637                 :             :           (BEST_PARITY, WORSE_PARITY) <known>
     638                 :             :                       |
     639                 :             :           (WORSE_PARITY, WORSE_PARITY) <calc>                (BEST_PARITY, 0) <known>
     640                 :             :                        \___________________________________________/
     641                 :             :                                               |
     642                 :             :                                        (WORSE_PARITY, 0)   <known>
     643                 :             :                                               |
     644                 :             :                                        (AB_PARITY_UNKN, 0) <known>
     645                 :             :                                               |
     646                 :             :                                        (AB_PARITY_UNDF, 0) <known>
     647                 :             :                                               |
     648                 :             :                                        <next pair of ranks>
     649                 :             :       Meaning:
     650                 :             :       stereo_bond_parity is the parity we are looking for
     651                 :             :       stereo_bond_parity==sb_parity_calc  => parity to be calculated from canonical numbers
     652                 :             :       stereo_bond_parity!=sb_parity_calc  => parity is already known
     653                 :             :      */
     654                 :           0 : get_next_parity:
     655   [ #  #  #  #  :           0 :     switch (*stereo_bond_parity)
                      # ]
     656                 :             :     {
     657                 :           0 :         case BEST_PARITY:
     658   [ #  #  #  # ]:           0 :             switch (*sb_parity_calc)
     659                 :             :             {
     660                 :           0 :                 case 0:                                 /*  BEST_PARITY(known) : (BEST_PARITY, 0) -> */
     661                 :           0 :                     *stereo_bond_parity = WORSE_PARITY;  /*  WORSE_PARITY(known): (WORSE_PARITY, 0) */
     662         [ #  # ]:           0 :                     if (!nNumWorse)
     663                 :             :                     {
     664                 :           0 :                         goto get_next_parity;
     665                 :             :                     }
     666                 :           0 :                     break;
     667                 :           0 :                 case BEST_PARITY:                       /*  BEST_PARITY(calc) : (BEST_PARITY, BEST_PARITY) -> */
     668                 :           0 :                     *sb_parity_calc = WORSE_PARITY;      /*  BEST_PARITY(known): (BEST_PARITY, WORSE_PARITY) */
     669         [ #  # ]:           0 :                     if (!nNumBest)
     670                 :             :                     {
     671                 :           0 :                         goto get_next_parity;
     672                 :             :                     }
     673                 :           0 :                     break;
     674                 :           0 :                 case WORSE_PARITY:                      /*  BEST_PARITY(known): (BEST_PARITY, WORSE_PARITY)-> */
     675                 :           0 :                     *stereo_bond_parity = WORSE_PARITY;  /*  WORSE_PARITY(calc): (WORSE_PARITY,WORSE_PARITY) */
     676         [ #  # ]:           0 :                     if (!nNumCalc)
     677                 :             :                     { /* added 12-17-2003 */
     678                 :           0 :                         goto get_next_parity;
     679                 :             :                     }
     680                 :           0 :                     break;
     681                 :             :             }
     682                 :           0 :             break;
     683                 :           0 :         case WORSE_PARITY:
     684   [ #  #  #  # ]:           0 :             switch (*sb_parity_calc)
     685                 :             :             {
     686                 :           0 :                 case 0:                                 /*  WORSE_PARITY(known)  : (WORSE_PARITY, 0) -> */
     687                 :           0 :                     *stereo_bond_parity = vABParityUnknown /* AB_PARITY_UNKN */;/*  AB_PARITY_UNKN(known): (AB_PARITY_UNKN, 0) */
     688         [ #  # ]:           0 :                     if (!nNumUnkn)
     689                 :             :                     {
     690                 :           0 :                         goto get_next_parity;
     691                 :             :                     }
     692                 :           0 :                     break;
     693                 :           0 :                 case BEST_PARITY:                       /*  error */
     694                 :           0 :                     return CT_STEREOCOUNT_ERR;          /*   <BRKPT> */
     695                 :           0 :                 case WORSE_PARITY:                      /*  WORSE_PARITY(calc) : (WORSE_PARITY,WORSE_PARITY)-> */
     696                 :           0 :                     *sb_parity_calc = 0;                 /*  WORSE_PARITY(known): (WORSE_PARITY, 0) */
     697         [ #  # ]:           0 :                     if (!nNumWorse)
     698                 :             :                     {
     699                 :           0 :                         goto get_next_parity;
     700                 :             :                     }
     701                 :           0 :                     break;
     702                 :             :             }
     703                 :           0 :             break;
     704                 :             : 
     705                 :           0 :         case AB_PARITY_UNKN:                        /* AB_PARITY_UNKN(known): (AB_PARITY_UNKN, 0) -> */
     706         [ #  # ]:           0 :             if (*sb_parity_calc)                 /*  error */
     707                 :             :             {
     708                 :           0 :                 return CT_STEREOCOUNT_ERR;          /*   <BRKPT> */
     709                 :             :             }
     710                 :           0 :             *stereo_bond_parity = AB_PARITY_UNDF;    /* AB_PARITY_UNDF(known): (AB_PARITY_UNDF, 0) */
     711         [ #  # ]:           0 :             if (!nNumUndf)
     712                 :             :             {
     713                 :           0 :                 return 1; /*goto next_canon_ranks;*/
     714                 :             :             }
     715                 :           0 :             break;
     716                 :             : 
     717                 :           0 :         case AB_PARITY_UNDF:                        /*  AB_PARITY_UNDF(known): (AB_PARITY_UNDF, 0) -> */
     718         [ #  # ]:           0 :             if (*sb_parity_calc)
     719                 :             :             {                /*  error */
     720                 :           0 :                 return CT_STEREOCOUNT_ERR;          /*   <BRKPT> */
     721                 :             :             }
     722                 :           0 :             return 1; /*goto next_canon_ranks;*/     /*  next canon ranks */
     723                 :             :     }
     724                 :           0 :     return 0;
     725                 :             : }
     726                 :             : 
     727                 :             : 
     728                 :             : /****************************************************************************/
     729                 :           0 : int CompareLinCtStereoDoubleToValues( AT_STEREO_DBLE *LinearCTStereoDble,
     730                 :             :                                       AT_RANK at_rank_canon1,
     731                 :             :                                       AT_RANK at_rank_canon2,
     732                 :             :                                       U_CHAR bond_parity )
     733                 :             : {
     734         [ #  # ]:           0 :     if (LinearCTStereoDble->at_num1 CT_GREATER_THAN at_rank_canon1)
     735                 :             :     {
     736                 :           0 :         return 1;
     737                 :             :     }
     738         [ #  # ]:           0 :     if (LinearCTStereoDble->at_num1 != at_rank_canon1)
     739                 :             :     {
     740                 :           0 :         return -1;
     741                 :             :     }
     742         [ #  # ]:           0 :     if (LinearCTStereoDble->at_num2 CT_GREATER_THAN at_rank_canon2)
     743                 :             :     {
     744                 :           0 :         return 1;
     745                 :             :     }
     746         [ #  # ]:           0 :     if (LinearCTStereoDble->at_num2 != at_rank_canon2)
     747                 :             :     {
     748                 :           0 :         return -1;
     749                 :             :     }
     750         [ #  # ]:           0 :     if (LinearCTStereoDble->parity CT_GREATER_THAN bond_parity)
     751                 :             :     {
     752                 :           0 :         return 1;
     753                 :             :     }
     754         [ #  # ]:           0 :     if (LinearCTStereoDble->parity != bond_parity)
     755                 :             :     {
     756                 :           0 :         return -1;
     757                 :             :     }
     758                 :             : 
     759                 :           0 :     return 0;
     760                 :             : }
     761                 :             : 
     762                 :             : 
     763                 :             : /****************************************************************************
     764                 :             :   Set for at[i]:
     765                 :             :    0                  if atom has no parity
     766                 :             :    STEREO_AT_MARK=8   if atom has stereo parity and has no stereo bonds
     767                 :             :    num_stereo_bonds   number of stereogenic bonds adjacent to the atom <= 3
     768                 :             : ****************************************************************************/
     769                 :         109 : void SetUseAtomForStereo( S_CHAR *bAtomUsedForStereo, sp_ATOM *at, int num_atoms )
     770                 :             : {
     771                 :             :     int i, k;
     772                 :         109 :     memset( bAtomUsedForStereo, 0, sizeof( bAtomUsedForStereo[0] )*num_atoms ); /* djb-rwth: memset_s C11/Annex K variant? */
     773         [ +  + ]:        1215 :     for (i = 0; i < num_atoms; i++)
     774                 :             :     {
     775         [ +  + ]:        1106 :         if (at[i].parity)
     776                 :             :         {
     777   [ +  -  -  + ]:         367 :             for (k = 0; k < MAX_NUM_STEREO_BONDS && at[i].stereo_bond_neighbor[k]; k++)
     778                 :             :             {
     779                 :             :                 ;
     780                 :             :             }
     781         [ -  + ]:         367 :             bAtomUsedForStereo[i] = k ? k : STEREO_AT_MARK;
     782                 :             :         }
     783                 :             :     }
     784                 :         109 : }
     785                 :             : 
     786                 :             : 
     787                 :             :  /****************************************************************************/
     788                 :          58 : int CurTreeAlloc( CUR_TREE *cur_tree, int num_atoms )
     789                 :             : {
     790         [ +  - ]:          58 :     if (cur_tree)
     791                 :             :     {
     792   [ -  +  -  -  :          58 :         if (cur_tree->tree && cur_tree->max_len > 0 && !( cur_tree->max_len % num_atoms ))
                   -  - ]
     793                 :             :         {
     794                 :             :             /*  do not reallocate */
     795                 :           0 :             cur_tree->cur_len = 0;
     796                 :           0 :             cur_tree->incr_len = num_atoms;
     797                 :           0 :             memset( cur_tree->tree, 0, cur_tree->max_len * sizeof( cur_tree->tree[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     798                 :           0 :             return 0; /*  ok */
     799                 :             :         }
     800         [ -  + ]:          58 :         inchi_free( cur_tree->tree );
     801                 :          58 :         memset( cur_tree, 0, sizeof( *cur_tree ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     802         [ +  - ]:          58 :         if ((cur_tree->tree = (AT_NUMB *) inchi_calloc( num_atoms, sizeof( cur_tree->tree[0] ) ))) /* djb-rwth: addressing LLVM warning */
     803                 :             :         {
     804                 :          58 :             cur_tree->incr_len =
     805                 :          58 :                 cur_tree->max_len = num_atoms;
     806                 :          58 :             return 0; /*  ok */
     807                 :             :         }
     808                 :             :     }
     809                 :             : 
     810                 :           0 :     return -1; /*  error */ /*   <BRKPT> */
     811                 :             : }
     812                 :             : 
     813                 :             : 
     814                 :             : /****************************************************************************/
     815                 :           0 : int CurTreeReAlloc( CUR_TREE *cur_tree )
     816                 :             : {
     817         [ #  # ]:           0 :     if (cur_tree)
     818                 :             :     {
     819   [ #  #  #  #  :           0 :         if (cur_tree->tree && cur_tree->max_len > 0 && cur_tree->incr_len > 0)
                   #  # ]
     820                 :             :         {
     821                 :           0 :             void *p = cur_tree->tree;
     822         [ #  # ]:           0 :             if ((cur_tree->tree = (AT_NUMB *) inchi_calloc( (long long)cur_tree->max_len + (long long)cur_tree->incr_len, sizeof( cur_tree->tree[0] ) ))) /* djb-rwth: cast operators added; addressing LLVM warning */
     823                 :             :             {
     824                 :           0 :                 memcpy(cur_tree->tree, p, cur_tree->cur_len * sizeof(cur_tree->tree[0]));
     825         [ #  # ]:           0 :                 inchi_free( p );
     826                 :           0 :                 cur_tree->max_len += cur_tree->incr_len;
     827                 :           0 :                 return 0; /*  ok */
     828                 :             :             }
     829                 :             :         }
     830                 :             :     }
     831                 :             : 
     832                 :           0 :     return -1; /*  error */ /*   <BRKPT> */
     833                 :             : }
     834                 :             : 
     835                 :             : 
     836                 :         161 : /****************************************************************************/void CurTreeFree( CUR_TREE *cur_tree )
     837                 :             : {
     838         [ +  + ]:         161 :     if (cur_tree)
     839                 :             :     {
     840         [ +  - ]:          58 :         inchi_free( cur_tree->tree );
     841                 :          58 :         memset( cur_tree, 0, sizeof( *cur_tree ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     842                 :             :     }
     843                 :         161 : }
     844                 :             : 
     845                 :             : 
     846                 :           0 : /****************************************************************************/int CurTreeAddRank( CUR_TREE *cur_tree, AT_NUMB rank )
     847                 :             : {
     848         [ #  # ]:           0 :     if (cur_tree)
     849                 :             :     {
     850         [ #  # ]:           0 :         if (cur_tree->cur_len + 2 > cur_tree->max_len)
     851                 :             :         {
     852         [ #  # ]:           0 :             if (CurTreeReAlloc( cur_tree ))
     853                 :             :             {
     854                 :           0 :                 return -1; /*  error */ /*   <BRKPT> */
     855                 :             :             }
     856                 :             :         }
     857                 :           0 :         cur_tree->tree[cur_tree->cur_len++] = rank;
     858                 :           0 :         cur_tree->tree[cur_tree->cur_len++] = 1;
     859                 :           0 :         return 0;
     860                 :             :     }
     861                 :             : 
     862                 :           0 :     return -1;  /*  error  */ /*   <BRKPT> */
     863                 :             : }
     864                 :             : 
     865                 :             : 
     866                 :             : /****************************************************************************/
     867                 :           0 : int CurTreeIsLastRank( CUR_TREE *cur_tree, AT_NUMB rank )
     868                 :             : {
     869   [ #  #  #  # ]:           0 :     if (cur_tree && cur_tree->cur_len > 0)
     870                 :             :     {
     871                 :             :         int rank_pos;
     872                 :           0 :         rank_pos = cur_tree->cur_len - 1;
     873                 :           0 :         rank_pos -= cur_tree->tree[rank_pos];
     874         [ #  # ]:           0 :         if (rank_pos >= 0)
     875                 :             :         {
     876                 :           0 :             return ( rank == cur_tree->tree[rank_pos] );
     877                 :             :         }
     878                 :             :     }
     879                 :             : 
     880                 :           0 :     return 0;  /*  not found */
     881                 :             : }
     882                 :             : 
     883                 :             : 
     884                 :             : /****************************************************************************/
     885                 :           0 : int CurTreeRemoveLastRankIfNoAtoms( CUR_TREE *cur_tree )
     886                 :             : {
     887   [ #  #  #  #  :           0 :     if (cur_tree && cur_tree->tree && cur_tree->cur_len >= 2)
                   #  # ]
     888                 :             :     {
     889         [ #  # ]:           0 :         if (1 == cur_tree->tree[cur_tree->cur_len - 1])
     890                 :             :         {
     891                 :           0 :             return CurTreeRemoveLastRank( cur_tree ); /*  0=> success, -1=>failed */
     892                 :             :         }
     893                 :           0 :         return 1; /*  cannot remove */
     894                 :             :     }
     895                 :           0 :     return -1; /*  error */ /*   <BRKPT> */
     896                 :             : }
     897                 :             : 
     898                 :             : 
     899                 :             : /****************************************************************************/
     900                 :           0 : int CurTreeAddAtom( CUR_TREE *cur_tree, int at_no )
     901                 :             : {
     902         [ #  # ]:           0 :     if (cur_tree)
     903                 :             :     {
     904         [ #  # ]:           0 :         if (cur_tree->cur_len + 1 > cur_tree->max_len)
     905                 :             :         {
     906         [ #  # ]:           0 :             if (CurTreeReAlloc( cur_tree ))
     907                 :             :             {
     908                 :           0 :                 return -1; /*  error */ /*   <BRKPT> */
     909                 :             :             }
     910                 :             :         }
     911         [ #  # ]:           0 :         if (cur_tree->cur_len > 0)
     912                 :             :         {
     913                 :           0 :             AT_NUMB new_len = cur_tree->tree[--cur_tree->cur_len] + 1;
     914                 :           0 :             cur_tree->tree[cur_tree->cur_len++] = (AT_NUMB) at_no;
     915                 :           0 :             cur_tree->tree[cur_tree->cur_len++] = new_len;
     916                 :           0 :             return 0;
     917                 :             :         }
     918                 :             :     }
     919                 :             : 
     920                 :           0 :     return -1;
     921                 :             : }
     922                 :             : 
     923                 :             : 
     924                 :             : /****************************************************************************/
     925                 :         117 : void CurTreeKeepLastAtomsOnly( CUR_TREE *cur_tree, int tpos, int shift )
     926                 :             : {   /*  on first entry: shift = 1; other values may occur in subsequent recursion */
     927                 :             :     /*  cur_tree[cur_tree->cur_len - shift] is the length of a segment */
     928                 :             :     /*  action: remove all atoms except the last from all segments
     929                 :             :                 that have length value positon to the right from tpos */
     930                 :             :     int cur_length_pos;
     931   [ +  -  +  -  :         117 :     if (cur_tree && cur_tree->tree && ( cur_length_pos = cur_tree->cur_len - shift ) > tpos)
                   -  + ]
     932                 :             :     {
     933         [ #  # ]:           0 :         if (cur_tree->tree[cur_length_pos] > 2)
     934                 :             :         {
     935                 :             :             /*  current segment contains more than 1 atom. Leave in the segment: rank, the last atom, length value */
     936                 :             :             /*  subtract (old segment length)-(new segment length) from the tree length  */
     937                 :             :             /*  actual segment length including segment length value = (cur_tree->tree[cur_length_pos]+1) */
     938                 :           0 :             cur_tree->cur_len -= (int) cur_tree->tree[cur_length_pos] - 2;
     939                 :           0 :             memmove(cur_tree->tree + cur_length_pos - cur_tree->tree[cur_length_pos] + 1, /*  1st atom pos */
     940                 :           0 :                 cur_tree->tree + cur_length_pos - 1,  /*  last atom in the current segment position */
     941                 :           0 :                 ((long long)shift + 1) * sizeof(cur_tree->tree[0])); /* djb-rwth: cast operator added */
     942                 :             :             /*  (current segment length) distance from the last tree element has not changed */
     943                 :           0 :             cur_tree->tree[cur_tree->cur_len - shift] = 2;
     944                 :             :             /*  add 3 to move to the previous segment length position */
     945                 :           0 :             shift += 3; /*  lenghth = 3 accounts for 3 currently present. segment items:
     946                 :             :                             (1) the last atom, (2) rank, (3) length value */
     947                 :             :         }
     948                 :             :         else
     949                 :             :         {
     950                 :           0 :             shift += (int) cur_tree->tree[cur_length_pos] + 1; /*  cur_tree->cur_len - (previous segment length position) */
     951                 :             :         }
     952                 :           0 :         CurTreeKeepLastAtomsOnly( cur_tree, tpos, shift );
     953                 :             :     }
     954                 :         117 : }
     955                 :             : 
     956                 :             : 
     957                 :             : /****************************************************************************/
     958                 :           0 : int CurTreeRemoveIfLastAtom( CUR_TREE *cur_tree, int at_no )
     959                 :             : {
     960   [ #  #  #  #  :           0 :     if (cur_tree && cur_tree->tree && cur_tree->cur_len > 2)
                   #  # ]
     961                 :             :     {
     962                 :           0 :         AT_NUMB len = cur_tree->tree[cur_tree->cur_len - 1];
     963   [ #  #  #  # ]:           0 :         if (len >= 2 && (int) cur_tree->tree[cur_tree->cur_len - 2] == at_no)
     964                 :             :         {
     965                 :           0 :             cur_tree->tree[--cur_tree->cur_len - 1] = len - 1;
     966                 :           0 :             return 0;
     967                 :             :         }
     968                 :           0 :         return 1; /*  not found */
     969                 :             :     }
     970                 :             : 
     971                 :           0 :     return -1; /*  error */ /*   <BRKPT> */
     972                 :             : }
     973                 :             : 
     974                 :             : 
     975                 :             : /****************************************************************************/
     976                 :        1686 : int CurTreeGetPos( CUR_TREE *cur_tree )
     977                 :             : {
     978         [ +  - ]:        1686 :     if (cur_tree)
     979                 :             :     {
     980                 :        1686 :         return cur_tree->cur_len;
     981                 :             :     }
     982                 :             : 
     983                 :           0 :     return -1;
     984                 :             : }
     985                 :             : 
     986                 :             : 
     987                 :             : /****************************************************************************/
     988                 :         894 : int CurTreeSetPos( CUR_TREE *cur_tree, int len )
     989                 :             : {
     990         [ +  - ]:         894 :     if (cur_tree)
     991                 :             :     {
     992                 :         894 :         cur_tree->cur_len = len;
     993                 :         894 :         return 0;
     994                 :             :     }
     995                 :             : 
     996                 :           0 :     return -1;
     997                 :             : }
     998                 :             : 
     999                 :             : 
    1000                 :             : /****************************************************************************/
    1001                 :           0 : int CurTreeRemoveLastRank( CUR_TREE *cur_tree )
    1002                 :             : {
    1003   [ #  #  #  # ]:           0 :     if (cur_tree && cur_tree->cur_len > 0)
    1004                 :             :     {
    1005                 :           0 :         cur_tree->cur_len -= cur_tree->tree[cur_tree->cur_len - 1] + 1;
    1006         [ #  # ]:           0 :         if (cur_tree->cur_len >= 0)
    1007                 :             :         {
    1008                 :           0 :             return 0;
    1009                 :             :         }
    1010                 :             :     }
    1011                 :             : 
    1012                 :           0 :     return -1;
    1013                 :             : }
    1014                 :             : 
    1015                 :             : 
    1016                 :             : /****************************************************************************
    1017                 :             :   Find if the atom is equivalent to already successfully tried current atoms
    1018                 :             : ****************************************************************************/
    1019                 :           0 : int CurTreeIsLastAtomEqu( CUR_TREE *cur_tree, int at_no, AT_NUMB *nSymmStereo )
    1020                 :             : {
    1021   [ #  #  #  #  :           0 :     if (cur_tree && cur_tree->tree && nSymmStereo && cur_tree->cur_len > 1)
             #  #  #  # ]
    1022                 :             :     {
    1023                 :           0 :         AT_NUMB nEq = nSymmStereo[at_no];
    1024                 :           0 :         int end = cur_tree->cur_len - 1;
    1025                 :           0 :         int len = cur_tree->tree[end] - 1;
    1026         [ #  # ]:           0 :         for (; len > 0; len--)
    1027                 :             :         {
    1028         [ #  # ]:           0 :             if (nSymmStereo[(int) cur_tree->tree[end - len]] == nEq)
    1029                 :           0 :                 return 1;
    1030                 :             :         }
    1031                 :           0 :         return 0;
    1032                 :             :     }
    1033                 :             : 
    1034                 :           0 :     return -1; /*  error */ /*   <BRKPT> */
    1035                 :             : }
    1036                 :             : 
    1037                 :             : 
    1038                 :             : #ifdef NEVER /* not used */
    1039                 :             : /****************************************************************************/
    1040                 :             : int CurTreeRemoveLastAtom( CUR_TREE *cur_tree )
    1041                 :             : {
    1042                 :             :     if (cur_tree && cur_tree->tree && cur_tree->cur_len > 2)
    1043                 :             :     {
    1044                 :             :         AT_NUMB len = cur_tree->tree[--cur_tree->cur_len];
    1045                 :             :         if (len >= 2)
    1046                 :             :         {
    1047                 :             :             cur_tree->tree[cur_tree->cur_len - 1] = len - 1;
    1048                 :             :             return 0;
    1049                 :             :         }
    1050                 :             :     }
    1051                 :             :     return -1;
    1052                 :             : }
    1053                 :             : 
    1054                 :             : 
    1055                 :             : /****************************************************************************/
    1056                 :             : int CurTreeReplaceLastRank( CUR_TREE *cur_tree, AT_NUMB rank )
    1057                 :             : {
    1058                 :             :     if (!CurTreeRemoveLastRank( cur_tree ))
    1059                 :             :     {
    1060                 :             :         return CurTreeAddRank( cur_tree, rank );
    1061                 :             :     }
    1062                 :             :     return -1;
    1063                 :             : }
    1064                 :             : 
    1065                 :             : 
    1066                 :             : /****************************************************************************
    1067                 :             :   returns cur_tree->cur_len for the block containing the rank
    1068                 :             : ****************************************************************************/
    1069                 :             : int CurTreeFindTheRankPos( CUR_TREE *cur_tree, AT_NUMB rank )
    1070                 :             : {
    1071                 :             :     int i, k;
    1072                 :             :     if (cur_tree && cur_tree->tree && ( i = cur_tree->cur_len ) > 0)
    1073                 :             :     {
    1074                 :             :         while (0 <= ( k = i - (int) cur_tree->tree[i - 1] - 1 ))
    1075                 :             :         {
    1076                 :             :             if (cur_tree->tree[k] == rank)
    1077                 :             :             {
    1078                 :             :                 return i;
    1079                 :             :             }
    1080                 :             :             i = k;
    1081                 :             :         }
    1082                 :             :     }
    1083                 :             : 
    1084                 :             :     return -1; /*  error */ /*   <BRKPT> */
    1085                 :             : }
    1086                 :             : #endif
        

Generated by: LCOV version 2.0-1