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

Generated by: LCOV version 2.0-1