LCOV - code coverage report
Current view: top level - src - ichisort.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 84.8 % 368 312
Test Date: 2026-10-14 12:14:55 Functions: 89.7 % 29 26
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 69.8 % 268 187

             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                 :             : #include "ichicant.h"
      11                 :             : 
      12                 :             : #include "bcf_s.h"
      13                 :             : 
      14                 :             : #if 0
      15                 :             : #define RET_MAX 32767
      16                 :             : #define CUTOFF 8            /* testing shows that this is good value */
      17                 :             : #endif
      18                 :             : 
      19                 :             : /* Note: the theoretical number of stack entries required is
      20                 :             : no more than 1 + log2(num).  But we switch to insertion
      21                 :             : sort for CUTOFF elements or less, so we really only need
      22                 :             : 1 + log2(num) - log2(CUTOFF) stack entries.  For a CUTOFF
      23                 :             : of 8, that means we need no more than 30 stack entries for
      24                 :             : 32 bit platforms, and 62 for 64-bit platforms. */
      25                 :             : #define STKSIZ (8*sizeof(void*) - 2)
      26                 :             : 
      27                 :             : 
      28                 :             : /****************************************************************************
      29                 :             :  inchi's qsort
      30                 :             : ****************************************************************************/
      31                 :         749 : void inchi_qsort( void *pParam,
      32                 :             :                   void *base,
      33                 :             :                   size_t num,
      34                 :             :                   size_t width,
      35                 :             :                   int( *comp )( const void *, const void *, void * ) )
      36                 :             : {
      37                 :             :     char *lo, *hi;              /* ends of sub-array currently sorting */
      38                 :             :     char *mid;                  /* points to middle of subarray */
      39                 :             :     char *loguy, *higuy;        /* traveling pointers for partition step */
      40                 :             :     size_t size;                /* size of the sub-array */
      41                 :             :     char *lostk[STKSIZ], *histk[STKSIZ];
      42                 :             :     int stkptr;                 /* stack for saving sub-array to be processed */
      43                 :             : 
      44         [ +  + ]:         749 :     if (num < 2)
      45                 :         354 :         return;                 /* nothing to do */
      46                 :             : 
      47                 :         395 :     stkptr = 0;                 /* initialize stack */
      48                 :             : 
      49                 :         395 :     lo = (char *) base;
      50                 :         395 :     hi = (char *) base + width * ( num - 1 );        /* initialize limits */
      51                 :             : 
      52                 :             :     /* This entry point is for pseudo-recursion calling: setting
      53                 :             :     lo and hi and jumping to here is like recursion, but stkptr is
      54                 :             :     preserved, locals aren't, so we preserve stuff on the stack */
      55                 :        1623 : recurse:
      56                 :             : 
      57                 :        2018 :     size = ( hi - lo ) / width + 1;        /* number of el's to sort */
      58                 :             : 
      59                 :             :     /* First we pick a partitioning element.  The efficiency of the
      60                 :             :     algorithm demands that we find one that is approximately the median
      61                 :             :     of the values, but also that we select one fast.  We choose the
      62                 :             :     median of the first, middle, and last elements, to avoid bad
      63                 :             :     performance in the face of already sorted data, or data that is made
      64                 :             :     up of multiple sorted runs appended together.  Testing shows that a
      65                 :             :     median-of-three algorithm provides better performance than simply
      66                 :             :     picking the middle element for the latter case. */
      67                 :             : 
      68                 :        2018 :     mid = lo + ( size / 2 ) * width;      /* find middle element */
      69                 :             : 
      70                 :             :     /* Sort the first, middle, last elements into order */
      71         [ +  + ]:        2018 :     if (comp( lo, mid, pParam ) > 0)
      72                 :             :     {
      73                 :         191 :         inchi_swap( lo, mid, width );
      74                 :             :     }
      75         [ +  + ]:        2018 :     if (comp( lo, hi, pParam ) > 0)
      76                 :             :     {
      77                 :          97 :         inchi_swap( lo, hi, width );
      78                 :             :     }
      79         [ +  + ]:        2018 :     if (comp( mid, hi, pParam ) > 0)
      80                 :             :     {
      81                 :         248 :         inchi_swap( mid, hi, width );
      82                 :             :     }
      83                 :             : 
      84                 :             :     /* We now wish to partition the array into three pieces, one consisting
      85                 :             :     of elements <= partition element, one of elements equal to the
      86                 :             :     partition element, and one of elements > than it.  This is done
      87                 :             :     below; comments indicate conditions established at every step. */
      88                 :             : 
      89                 :        2018 :     loguy = lo;
      90                 :        2018 :     higuy = hi;
      91                 :             : 
      92                 :             :     /* Note that higuy decreases and loguy increases on every iteration,
      93                 :             :     so loop must terminate. */
      94                 :             :     for (;;)
      95                 :             :     {
      96                 :             :         /* lo <= loguy < hi, lo < higuy <= hi,
      97                 :             :         A[i] <= A[mid] for lo <= i <= loguy,
      98                 :             :         A[i] > A[mid] for higuy <= i < hi,
      99                 :             :         A[hi] >= A[mid] */
     100                 :             : 
     101                 :             :         /* The doubled loop is to avoid calling comp(mid,mid), since some
     102                 :             :         existing comparison funcs don't work when passed the same
     103                 :             :         value for both pointers. */
     104                 :             : 
     105         [ +  + ]:        2265 :         if (mid > loguy)
     106                 :             :         {
     107                 :             :             do
     108                 :             :             {
     109                 :        4247 :                 loguy += width;
     110                 :             :             }
     111   [ +  +  +  + ]:        4247 :             while (loguy < mid && comp( loguy, mid, pParam ) <= 0);
     112                 :             :         }
     113         [ +  + ]:        2265 :         if (mid <= loguy)
     114                 :             :         {
     115                 :             :             do
     116                 :             :             {
     117                 :        2216 :                 loguy += width;
     118                 :             :             }
     119   [ +  +  +  + ]:        2216 :             while (loguy <= hi && comp( loguy, mid, pParam ) <= 0);
     120                 :             :         }
     121                 :             : 
     122                 :             :         /* lo < loguy <= hi+1, A[i] <= A[mid] for lo <= i < loguy,
     123                 :             :         either loguy > hi or A[loguy] > A[mid] */
     124                 :             : 
     125                 :             :         do
     126                 :             :         {
     127                 :        3906 :             higuy -= width;
     128                 :             :         }
     129   [ +  +  +  + ]:        3906 :         while (higuy > mid && comp( higuy, mid, pParam ) > 0);
     130                 :             : 
     131                 :             :          /* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi,
     132                 :             :          either higuy == lo or A[higuy] <= A[mid] */
     133                 :             : 
     134         [ +  + ]:        2265 :         if (higuy < loguy)
     135                 :             :         {
     136                 :        2018 :             break;
     137                 :             :         }
     138                 :             : 
     139                 :             :         /* if loguy > hi or higuy == lo, then we would have exited, so
     140                 :             :         A[loguy] > A[mid], A[higuy] <= A[mid],
     141                 :             :         loguy <= hi, higuy > lo */
     142                 :             : 
     143                 :         247 :         inchi_swap( loguy, higuy, width );
     144                 :             : 
     145                 :             :         /* If the partition element was moved, follow it.  Only need
     146                 :             :         to check for mid == higuy, since before the swap,
     147                 :             :         A[loguy] > A[mid] implies loguy != mid. */
     148                 :             : 
     149         [ +  + ]:         247 :         if (mid == higuy)
     150                 :             :         {
     151                 :         119 :             mid = loguy;
     152                 :             :         }
     153                 :             : 
     154                 :             :         /* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition at top
     155                 :             :         of loop is re-established */
     156                 :             :     }
     157                 :             : 
     158                 :             :     /*     A[i] <= A[mid] for lo <= i < loguy,
     159                 :             :     A[i] > A[mid] for higuy < i < hi,
     160                 :             :     A[hi] >= A[mid]
     161                 :             :     higuy < loguy
     162                 :             :     implying:
     163                 :             :     higuy == loguy-1
     164                 :             :     or higuy == hi - 1, loguy == hi + 1, A[hi] == A[mid] */
     165                 :             : 
     166                 :             :     /* Find adjacent elements equal to the partition element.  The
     167                 :             :     doubled loop is to avoid calling comp(mid,mid), since some
     168                 :             :     existing comparison funcs don't work when passed the same value
     169                 :             :     for both pointers. */
     170                 :             : 
     171                 :        2018 :     higuy += width;
     172         [ +  + ]:        2018 :     if (mid < higuy)
     173                 :             :     {
     174                 :             :         do
     175                 :             :         {
     176                 :        1339 :             higuy -= width;
     177                 :             :         }
     178   [ +  +  -  + ]:        1339 :         while (higuy > mid && comp( higuy, mid, pParam ) == 0);
     179                 :             :     }
     180         [ +  + ]:        2018 :     if (mid >= higuy)
     181                 :             :     {
     182                 :             :         do
     183                 :             :         {
     184                 :        1908 :             higuy -= width;
     185                 :             :         }
     186   [ +  +  -  + ]:        1908 :         while (higuy > lo && comp( higuy, mid, pParam ) == 0);
     187                 :             :     }
     188                 :             : 
     189                 :             :     /* OK, now we have the following:
     190                 :             :     higuy < loguy
     191                 :             :     lo <= higuy <= hi
     192                 :             :     A[i]  <= A[mid] for lo <= i <= higuy
     193                 :             :     A[i]  == A[mid] for higuy < i < loguy
     194                 :             :     A[i]  >  A[mid] for loguy <= i < hi
     195                 :             :     A[hi] >= A[mid] */
     196                 :             : 
     197                 :             :     /* We've finished the partition, now we want to sort the subarrays
     198                 :             :     [lo, higuy] and [loguy, hi].
     199                 :             :     We do the smaller one first to minimize stack usage.
     200                 :             :     We only sort arrays of length 2 or more.*/
     201                 :             : 
     202         [ +  + ]:        2018 :     if (higuy - lo >= hi - loguy)
     203                 :             :     {
     204         [ +  + ]:        1906 :         if (lo < higuy)
     205                 :             :         {
     206                 :         950 :             lostk[stkptr] = lo;
     207                 :         950 :             histk[stkptr] = higuy;
     208                 :         950 :             ++stkptr;
     209                 :             :         }                           /* save big recursion for later */
     210                 :             : 
     211         [ +  + ]:        1906 :         if (loguy < hi)
     212                 :             :         {
     213                 :         521 :             lo = loguy;
     214                 :         521 :             goto recurse;           /* do small recursion */
     215                 :             :         }
     216                 :             :     }
     217                 :             :     else
     218                 :             :     {
     219         [ +  - ]:         112 :         if (loguy < hi)
     220                 :             :         {
     221                 :         112 :             lostk[stkptr] = loguy;
     222                 :         112 :             histk[stkptr] = hi;
     223                 :         112 :             ++stkptr;               /* save big recursion for later */
     224                 :             :         }
     225                 :             : 
     226         [ +  + ]:         112 :         if (lo < higuy)
     227                 :             :         {
     228                 :          40 :             hi = higuy;
     229                 :          40 :             goto recurse;           /* do small recursion */
     230                 :             :         }
     231                 :             :     }
     232                 :             : 
     233                 :             :     /* We have sorted the array, except for any pending sorts on the stack.
     234                 :             :     Check if there are any, and do them. */
     235                 :             : 
     236                 :        1457 :     --stkptr;
     237         [ +  + ]:        1457 :     if (stkptr >= 0)
     238                 :             :     {
     239                 :        1062 :         lo = lostk[stkptr];
     240                 :        1062 :         hi = histk[stkptr];
     241                 :        1062 :         goto recurse;           /* pop subarray from stack */
     242                 :             :     }
     243                 :             :     else
     244                 :             :     {
     245                 :         395 :         return;                 /* all subarrays done */
     246                 :             :     }
     247                 :             : }
     248                 :             : 
     249                 :             : 
     250                 :             : /****************************************************************************/
     251                 :        4322 : void inchi_swap( char *a, char *b, size_t width )
     252                 :             : {
     253                 :             :     char tmp;
     254         [ +  - ]:        4322 :     if (a != b)
     255                 :             :     {
     256         [ +  + ]:       15248 :         while (width--)
     257                 :             :         {
     258                 :       10926 :             tmp = *a;
     259                 :       10926 :             *a++ = *b;
     260                 :       10926 :             *b++ = tmp;
     261                 :             :         }
     262                 :             :     }
     263                 :        4322 : }
     264                 :             : 
     265                 :             : 
     266                 :             : /****************************************************************************
     267                 :             :  Sort by insertions
     268                 :             : ****************************************************************************/
     269                 :        4089 : int insertions_sort( void *pCG,
     270                 :             :                      void *base,
     271                 :             :                      size_t num, size_t width,
     272                 :             :                      int( *compare )( const void *, const void *, void * ) ) /* djb-rwth: types of variables are sufficient */
     273                 :             : {
     274                 :        4089 :     char *i, *j, *pk = (char*) base;
     275                 :        4089 :     int  num_trans = 0;
     276                 :             :     size_t k;
     277         [ +  + ]:       12795 :     for (k = 1; k < num; k++, pk += width)
     278                 :             :     {
     279                 :             :         /*for( i = pk, j = pk + width; j > (char*)base && (*compare)(i,j) > 0; j=i, i -= width )*/
     280                 :        8706 :         for (i = j = pk + width;
     281   [ +  +  +  + ]:       11731 :              j > ( char* )base && ( i -= width, ( *compare )( i, j, pCG ) ) > 0;
     282                 :        3025 :              j = i)        /* changed to keep BoundsChecker happy 2007-09-24 DT */
     283                 :             :         {
     284                 :        3025 :             inchi_swap( i, j, width );
     285                 :        3025 :             num_trans++;
     286                 :             :         }
     287                 :             :     }
     288                 :             : 
     289                 :        4089 :     return num_trans;
     290                 :             : }
     291                 :             : 
     292                 :             : 
     293                 :             : /****************************************************************************
     294                 :             :  Sort by insertions
     295                 :             : ****************************************************************************/
     296                 :         593 : int insertions_sort_AT_NUMBERS( void *pCG,
     297                 :             :                                 AT_NUMB *base,
     298                 :             :                                 int num,
     299                 :             :                                 int( *compare )( const void *e1, const void *e2, void * ) )
     300                 :             : {
     301                 :             :     AT_NUMB *i, *j, *pk, tmp;
     302                 :         593 :     int  k, num_trans = 0;
     303         [ +  + ]:        1354 :     for (k = 1, pk = base; k < num; k++, pk++)
     304                 :             :     {
     305   [ +  +  +  + ]:         865 :         for (j = ( i = pk ) + 1, tmp = *j; j > base && ( *compare )( i, &tmp, pCG ) > 0; j = i, i--)
     306                 :             :         {
     307                 :         104 :             *j = *i;
     308                 :         104 :             num_trans++;
     309                 :             :         }
     310                 :         761 :         *j = tmp;
     311                 :             :     }
     312                 :             : 
     313                 :         593 :     return num_trans;
     314                 :             : }
     315                 :             : 
     316                 :             : 
     317                 :             : /****************************************************************************
     318                 :             :  Sort neighbors according to ranks in ascending order
     319                 :             : ****************************************************************************/
     320                 :        2176 : void insertions_sort_NeighList_AT_NUMBERS( NEIGH_LIST base, AT_RANK *nRank )
     321                 :             : {
     322                 :             :     AT_NUMB *i, *j, *pk, tmp;
     323                 :             :     AT_RANK rj; /* optimization */
     324                 :        2176 :     int k, num = (int) *base++;
     325         [ +  + ]:        5723 :     for (k = 1, pk = base; k < num; k++, pk++)
     326                 :             :     {
     327   [ +  +  +  + ]:        3984 :         for (j = ( i = pk ) + 1, rj = nRank[(int) *j]; j > base && nRank[(int) *i] > rj; j = i, i--)
     328                 :             :         {
     329                 :         437 :             tmp = *i;
     330                 :         437 :             *i = *j;
     331                 :         437 :             *j = tmp;
     332                 :             :         }
     333                 :             :     }
     334                 :        2176 : }
     335                 :             : 
     336                 :             : 
     337                 :             : /****************************************************************************
     338                 :             :  Sort neighbors according to ranks in ascending order
     339                 :             : ****************************************************************************/
     340                 :           0 : int insertions_sort_AT_RANK( AT_RANK *base, int num )
     341                 :             : {
     342                 :             :     AT_RANK *i, *j, *pk, tmp;
     343                 :           0 :     int  k, num_trans = 0;
     344         [ #  # ]:           0 :     for (k = 1, pk = base; k < num; k++, pk++)
     345                 :             :     {
     346   [ #  #  #  # ]:           0 :         for (j = ( i = pk ) + 1, tmp = *j; j > base && *i > tmp; j = i, i--)
     347                 :             :         {
     348                 :           0 :             *j = *i;
     349                 :           0 :             num_trans++;
     350                 :             :         }
     351                 :           0 :         *j = tmp;
     352                 :             :     }
     353                 :             : 
     354                 :           0 :     return num_trans;
     355                 :             : }
     356                 :             : 
     357                 :             : 
     358                 :             : /****************************************************************************
     359                 :             :  Sort neighbors according to ranks in ascending order
     360                 :             : ****************************************************************************/
     361                 :         924 : int insertions_sort_NeighList_AT_NUMBERS3( NEIGH_LIST base, AT_RANK *nRank )
     362                 :             : {
     363                 :             :     AT_NUMB *i, *j, *pk, tmp;
     364                 :             :     AT_RANK rj;
     365                 :         924 :     int k, n, num = (int) *base++;
     366         [ +  + ]:        2128 :     for (k = 1, pk = base, n = 0; k < num; k++, pk++)
     367                 :             :     {
     368                 :        1204 :         for (j = ( i = pk ) + 1, rj = nRank[(int) ( tmp = *j )];
     369   [ +  +  +  + ]:        1219 :              j > base && nRank[(int) *i] > rj;
     370                 :          15 :              j = i, i--)
     371                 :             :         {
     372                 :          15 :             *j = *i;
     373                 :          15 :             n++;
     374                 :             :         }
     375                 :        1204 :         *j = tmp;
     376                 :             :     }
     377                 :             : 
     378                 :         924 :     return n;
     379                 :             : }
     380                 :             : 
     381                 :             : 
     382                 :             : /****************************************************************************
     383                 :             :  Sort neighbors according to symm. ranks (primary key) and canon.
     384                 :             :  ranks (secondary key), in descending order
     385                 :             : ****************************************************************************/
     386                 :        3318 : void insertions_sort_NeighListBySymmAndCanonRank( NEIGH_LIST base,
     387                 :             :                                                   const AT_RANK *nSymmRank,
     388                 :             :                                                   const AT_RANK *nCanonRank )
     389                 :             : {
     390                 :             :     AT_NUMB *i, *j, *pk, tmp;
     391                 :             :     int  diff;
     392                 :        3318 :     int k, num = (int) *base++;
     393         [ +  + ]:        6120 :     for (k = 1, pk = base; k < num; k++, pk++)
     394                 :             :     {
     395                 :        2802 :         for (j = ( i = pk ) + 1;
     396         [ +  + ]:        4959 :              j > base &&    /*  always j > i */
     397   [ +  +  +  + ]:        3702 :              ( 0 > ( diff = (int) nSymmRank[(int) *i] - (int) nSymmRank[(int) *j] ) ||
     398         [ +  - ]:          96 :              (!diff && nCanonRank[(int) *i] < nCanonRank[(int) *j]) ); /* djb-rwth: addressing LLVM warning */
     399                 :        2157 :              j = i, i--)
     400                 :             :         {
     401                 :        2157 :             tmp = *i;
     402                 :        2157 :             *i = *j;
     403                 :        2157 :             *j = tmp;
     404                 :             :         }
     405                 :             :     }
     406                 :             : 
     407                 :        3318 : }
     408                 :             : 
     409                 :             : 
     410                 :             : /****************************************************************************
     411                 :             :  *
     412                 :             :  *  Comparison functions
     413                 :             :  *
     414                 :             :  ****************************************************************************/
     415                 :             : 
     416                 :             : 
     417                 :             : /****************************************************************************/
     418                 :        2091 : int CompNeighborsAT_NUMBER( const void* a1, const void* a2, void *p )
     419                 :             : {
     420                 :        2091 :     CANON_GLOBALS *pCG = (CANON_GLOBALS *) p;
     421                 :             : #ifdef CT_NEIGH_INCREASE
     422                 :        4182 :     return (int) pCG->m_pn_RankForSort[pCG->m_pNeighborsForSort[( int )*(const AT_NUMB*) a1]] -
     423                 :        2091 :            (int) pCG->m_pn_RankForSort[pCG->m_pNeighborsForSort[( int )*(const AT_NUMB*) a2]];
     424                 :             : #else
     425                 :             :     return (int) ( (CANON_GLOBALS *) pCG )->m_pn_RankForSort[pNeighborsForSort[( int )*(const AT_NUMB*) a2]] -
     426                 :             :            (int) ( (CANON_GLOBALS *) pCG )->m_pn_RankForSort[pNeighborsForSort[( int )*(const AT_NUMB*) a1]];
     427                 :             : #endif
     428                 :             : }
     429                 :             : 
     430                 :             : 
     431                 :             : /**********************************************************************************/
     432                 :         741 : int comp_AT_RANK( const void* a1, const void* a2, void *p )
     433                 :             : {
     434                 :         741 :     return ( int )*(const AT_RANK*) a1 - ( int )*(const AT_RANK*) a2;
     435                 :             : }
     436                 :             : 
     437                 :             : 
     438                 :             : /**********************************************************************************/
     439                 :             : /*  Compare for sorting Ranks only */
     440                 :        1964 : int CompRank( const void* a1, const void* a2, void *p )
     441                 :             : {
     442                 :        1964 :     CANON_GLOBALS *pCG = (CANON_GLOBALS *) p;
     443                 :        1964 :     int ret = (int) pCG->m_pn_RankForSort[( int )*(const AT_RANK*) a1] -
     444                 :        1964 :               (int) pCG->m_pn_RankForSort[( int )*(const AT_RANK*) a2];
     445                 :             : 
     446                 :        1964 :     return ret;
     447                 :             : }
     448                 :             : 
     449                 :             : 
     450                 :             : /**********************************************************************************/
     451                 :        9426 : int CompRanksOrd( const void* a1, const void* a2, void *p )
     452                 :             : {
     453                 :             :     int ret;
     454                 :        9426 :     CANON_GLOBALS *pCG = (CANON_GLOBALS *) p;
     455                 :        9426 :     ret = (int) pCG->m_pn_RankForSort[( int )*(const AT_RANK*) a1] -
     456                 :        9426 :           (int) pCG->m_pn_RankForSort[( int )*(const AT_RANK*) a2];
     457         [ +  + ]:        9426 :     if (!ret)
     458                 :             :     {
     459                 :        2292 :         ret = ( int )*(const AT_RANK*) a1 - ( int )*(const AT_RANK*) a2;
     460                 :             :     }
     461                 :             : 
     462                 :        9426 :     return ret;
     463                 :             : }
     464                 :             : 
     465                 :             : 
     466                 :             : /**********************************************************************************/
     467                 :        4145 : int CompAtomInvariants2Only( const void* a1, const void* a2, void *p )
     468                 :             : {
     469                 :        4145 :     CANON_GLOBALS *pCG = (CANON_GLOBALS *) p;
     470                 :        4145 :     const ATOM_INVARIANT2 *pAI1 = pCG->m_pAtomInvariant2ForSort + ( int )*(const AT_RANK*) a1;
     471                 :        4145 :     const ATOM_INVARIANT2 *pAI2 = pCG->m_pAtomInvariant2ForSort + ( int )*(const AT_RANK*) a2;
     472                 :             :     int i;
     473         [ +  + ]:       20633 :     for (i = 0; i < AT_INV_BREAK1; i++)
     474                 :             :     {
     475         [ +  + ]:       18374 :         if (pAI1->val[i] == pAI2->val[i])
     476                 :       16488 :             continue;
     477                 :        1886 :         return  (int) pAI1->val[i] - (int) pAI2->val[i];
     478                 :             :     }
     479         [ -  + ]:        2259 :     if (pAI1->iso_sort_key != pAI2->iso_sort_key)
     480                 :             :     {
     481         [ #  # ]:           0 :         return ( pAI1->iso_sort_key > pAI2->iso_sort_key ) ? 1 : -1;
     482                 :             :     }
     483         [ +  - ]:        2259 :     for (; i < AT_INV_LENGTH; i++)
     484                 :             :     {
     485         [ -  + ]:        2259 :         if (pAI1->val[i] != pAI2->val[i])
     486                 :             :         {
     487                 :           0 :             continue;
     488                 :             :         }
     489                 :        2259 :         return  (int) pAI1->val[i] - (int) pAI2->val[i];
     490                 :             :     }
     491         [ #  # ]:           0 :     if (pAI1->iso_aux_key != pAI2->iso_aux_key)
     492                 :             :     {
     493         [ #  # ]:           0 :         return ( pAI1->iso_aux_key > pAI2->iso_aux_key ) ? 1 : -1;
     494                 :             :     }
     495                 :             : 
     496                 :           0 :     return 0;
     497                 :             : }
     498                 :             : 
     499                 :             : 
     500                 :             : /**********************************************************************************/
     501                 :        3398 : int CompAtomInvariants2( const void* a1, const void* a2, void *p )
     502                 :             : {
     503                 :             :     /*  Warning: the following line may be compiler implementation dependent */
     504                 :        3398 :     int ret = CompAtomInvariants2Only( a1, a2, p );
     505         [ +  + ]:        3398 :     if (!ret)
     506                 :             :     {
     507                 :        1755 :         ret = ( int )*(const AT_RANK*) a1 - ( int )*(const AT_RANK*) a2;
     508                 :             :     }
     509                 :             : 
     510                 :        3398 :     return ret;
     511                 :             : }
     512                 :             : 
     513                 :             : 
     514                 :             : /**********************************************************************************/
     515                 :             : /*  Compare two elements lexicographically */
     516                 :          50 : int CompChemElemLex( const void *a1, const void *a2 )
     517                 :             : {
     518                 :          50 :     return memcmp( a1, a2, 2 );
     519                 :             : }
     520                 :             : 
     521                 :             : 
     522                 :             : /****************************************************************************
     523                 :             :  Lexicographic compare
     524                 :             : ****************************************************************************/
     525                 :        3974 : int CompareNeighListLex( NEIGH_LIST pp1, NEIGH_LIST pp2, const AT_RANK *nRank )
     526                 :             : {
     527                 :        3974 :     int len1 = (int) *pp1++;
     528                 :        3974 :     int len2 = (int) *pp2++;
     529                 :        3974 :     int len = inchi_min( len1, len2 );
     530                 :        3974 :     int diff = 0;
     531                 :             :     int ret;
     532                 :             :     /* djb-rwth: fixing oss-fuzz issue #25642 */
     533   [ +  +  +  + ]:       10000 :     while ((len > 0) && !diff) 
     534                 :             :     {
     535                 :        6026 :         len--;
     536                 :        6026 :         diff = (int)nRank[*pp1++] - (int)nRank[*pp2++];
     537                 :             :     };
     538                 :             : 
     539         [ +  + ]:        3974 :     ret = diff ? diff : (len1 - len2);
     540                 :        3974 :     return ret;
     541                 :             : }
     542                 :             : 
     543                 :             : 
     544                 :             : /****************************************************************************
     545                 :             :  Lexicographic compare
     546                 :             : ****************************************************************************/
     547                 :         578 : int CompareNeighListLexUpToMaxRank( NEIGH_LIST pp1, NEIGH_LIST pp2, const AT_RANK *nRank, AT_RANK nMaxAtNeighRank )
     548                 :             : {
     549                 :         578 :     int len1 = (int) *pp1++;
     550                 :         578 :     int len2 = (int) *pp2++;
     551                 :         578 :     int diff = 0;
     552                 :             :     int len;
     553   [ +  -  +  + ]:        1019 :     while (0 < len1 && nRank[pp1[len1 - 1]] > nMaxAtNeighRank)
     554                 :             :     {
     555                 :         441 :         len1--;
     556                 :             :     }
     557   [ +  -  +  + ]:        1019 :     while (0 < len2 && nRank[pp2[len2 - 1]] > nMaxAtNeighRank)
     558                 :             :     {
     559                 :         441 :         len2--;
     560                 :             :     }
     561                 :         578 :     len = inchi_min( len1, len2 );
     562   [ +  +  +  + ]:        1244 :     while (len-- > 0 && !( diff = (int) nRank[*pp1++] - (int) nRank[*pp2++] ))
     563                 :             :     {
     564                 :             :         ;
     565                 :             :     }
     566                 :             : 
     567         [ +  + ]:         578 :     return diff ? diff : ( len1 - len2 );
     568                 :             : }
     569                 :             : 
     570                 :             : 
     571                 :             : /****************************************************************************/
     572                 :        3492 : int compare_NeighLists( const NEIGH_LIST *op1, const NEIGH_LIST *op2, void *p )
     573                 :             : {
     574                 :        3492 :     CANON_GLOBALS *pCG = (CANON_GLOBALS *) p;
     575                 :        3492 :     return CompareNeighListLex( *op1, *op2, pCG->m_pn_RankForSort );
     576                 :             : }
     577                 :             : 
     578                 :             : 
     579                 :             : /****************************************************************************/
     580                 :        7698 : int CompNeighListRanks( const void* a1, const void* a2, void *p )
     581                 :             : {
     582                 :        7698 :     CANON_GLOBALS *pCG = (CANON_GLOBALS *) p;
     583                 :             :     int ret;
     584                 :        7698 :     ret = (int) pCG->m_pn_RankForSort[*( (const AT_RANK*) a1 )] -
     585                 :        7698 :           (int) pCG->m_pn_RankForSort[*( (const AT_RANK*) a2 )];
     586         [ +  + ]:        7698 :     if (!ret)
     587                 :             :     {
     588                 :        2985 :         ret = compare_NeighLists( pCG->m_pNeighList_RankForSort + *( (const AT_RANK*) a1 ),
     589                 :        2985 :                                      pCG->m_pNeighList_RankForSort + *( (const AT_RANK*) a2 ), p );
     590                 :             :     }
     591                 :             : 
     592                 :        7698 :     return ret;
     593                 :             : }
     594                 :             : 
     595                 :             : 
     596                 :             : /****************************************************************************/
     597                 :         507 : int CompNeighLists( const void* a1, const void* a2, void *p )
     598                 :             : {
     599                 :         507 :     CANON_GLOBALS *pCG = (CANON_GLOBALS *) p;
     600                 :             :     int ret;
     601                 :         507 :     ret = compare_NeighLists( pCG->m_pNeighList_RankForSort + *( (const AT_RANK*) a1 ),
     602                 :         507 :                               pCG->m_pNeighList_RankForSort + *( (const AT_RANK*) a2 ), p );
     603                 :             : 
     604                 :         507 :     return ret;
     605                 :             : }
     606                 :             : 
     607                 :             : 
     608                 :             : /****************************************************************************/
     609                 :         299 : int CompNeighListsUpToMaxRank( const void* a1, const void* a2, void *p )
     610                 :             : {
     611                 :         299 :     CANON_GLOBALS *pCG = (CANON_GLOBALS *) p;
     612                 :             :     int ret;
     613                 :         299 :     ret = CompareNeighListLexUpToMaxRank( pCG->m_pNeighList_RankForSort[*( (const AT_RANK*) a1 )],
     614                 :         299 :                                           pCG->m_pNeighList_RankForSort[*( (const AT_RANK*) a2 )],
     615                 :         299 :                                           pCG->m_pn_RankForSort, pCG->m_nMaxAtNeighRankForSort );
     616                 :             : 
     617                 :         299 :     return ret;
     618                 :             : }
     619                 :             : 
     620                 :             : 
     621                 :             : /****************************************************************************/
     622                 :        4219 : int CompNeighListRanksOrd( const void* a1, const void* a2, void *p )
     623                 :             : {
     624                 :        4219 :     int ret = CompNeighListRanks( a1, a2, p );
     625         [ +  + ]:        4219 :     if (!ret)
     626                 :             :     {
     627                 :         811 :         ret = ( int )*( (const AT_RANK*) a1 ) - ( int )*( (const AT_RANK*) a2 ); /*  keep original order if identical */
     628                 :             :     }
     629                 :             : 
     630                 :        4219 :     return ret;
     631                 :             : }
     632                 :             : 
     633                 :             : 
     634                 :             : /****************************************************************************/
     635                 :           0 : int CompRanksInvOrd( const void* a1, const void* a2, void *p )
     636                 :             : {
     637                 :           0 :     return ( int )*(const AT_RANK*) a2 - ( int )*(const AT_RANK*) a1;
     638                 :             : }
     639                 :             : 
     640                 :             : 
     641                 :             : /****************************************************************************/
     642                 :           0 : int CompNeighborsRanksCountEql( const void* a1, const void* a2, void *p )
     643                 :             : {
     644                 :           0 :     CANON_GLOBALS *pCG = (CANON_GLOBALS *) p;
     645                 :             : #ifdef CT_NEIGH_INCREASE
     646                 :           0 :     int ret = (int) pCG->m_pn_RankForSort[( int )*(const AT_RANK*) a1] -
     647                 :           0 :               (int) pCG->m_pn_RankForSort[( int )*(const AT_RANK*) a2];
     648                 :             : #else
     649                 :             :     int ret = (int) pCG->m_pn_RankForSort[( int )*(const AT_RANK*) a2] -
     650                 :             :               (int) pCG->m_pn_RankForSort[( int )*(const AT_RANK*) a1];
     651                 :             : #endif
     652                 :           0 :     pCG->m_nNumCompNeighborsRanksCountEql += !ret;
     653                 :             : 
     654                 :           0 :     return ret;
     655                 :             : }
     656                 :             : 
     657                 :             : 
     658                 :             : /****************************************************************************
     659                 :             :  *
     660                 :             :  * In this neighbor list the (vertex number) = (canonical number) - 1
     661                 :             :  * Since LinearCT is sorted so that parents are in ascending order
     662                 :             :  * and all neighbors of a parent are smaller than the parent and are
     663                 :             :  * in ascending order, the neighbors in the NEIGH_LIST are automatically
     664                 :             :  * sorted in ascending order
     665                 :             : ****************************************************************************/
     666                 :          70 : NEIGH_LIST *CreateNeighListFromLinearCT( AT_NUMB *LinearCT, int nLenCT, int num_atoms )
     667                 :             : {
     668                 :             :     /* Atom numbers in LinearCT are canonical numbers
     669                 :             :      * order: parent[i] > neigh[i][0] < neigh[i][1]...<neigh[i][n] < parent[i+1] > neigh[i+1][0] < ...
     670                 :             :      *        parent[i] < parent[i+1]
     671                 :             :      */
     672                 :             :     int i, j;
     673                 :          70 :     S_CHAR     *valence = NULL;
     674                 :          70 :     NEIGH_LIST *pp = NULL;
     675                 :          70 :     AT_NUMB    *pAtList = NULL;
     676                 :             :     AT_RANK     n_vertex, n_neigh;
     677                 :          70 :     int err = 1, num_bonds;
     678                 :             :     int length, start;
     679                 :             : 
     680         [ -  + ]:          70 :     if ((int) LinearCT[0] > num_atoms)
     681                 :             :     {
     682                 :           0 :         goto exit_function;
     683                 :             :     }
     684                 :          70 :     valence = (S_CHAR*)inchi_calloc((long long)num_atoms + 1, sizeof(valence[0]));
     685         [ -  + ]:          70 :     if (!valence) /* djb-rwth: cast operator added */
     686                 :             :     {
     687                 :           0 :         goto exit_function;
     688                 :             :     }
     689                 :             : 
     690         [ +  + ]:        1219 :     for (i = 1, num_bonds = 0, n_vertex = LinearCT[0]; i < nLenCT; i++)
     691                 :             :     {
     692         [ +  + ]:        1149 :         if (( n_neigh = LinearCT[i] ) < n_vertex)
     693                 :             :         {
     694                 :         587 :             valence[n_neigh] ++;
     695                 :         587 :             valence[n_vertex] ++;
     696                 :         587 :             num_bonds += 2;
     697                 :             :         }
     698                 :             :         else
     699                 :             :         {
     700         [ -  + ]:         562 :             if ((int) ( n_vertex = n_neigh ) > num_atoms)
     701                 :             :             {
     702                 :           0 :                 goto exit_function;
     703                 :             :             }
     704                 :             :         }
     705                 :             :     }
     706         [ -  + ]:          70 :     if ((int) n_vertex != num_atoms)
     707                 :             :     {
     708                 :           0 :         goto exit_function;
     709                 :             :     }
     710                 :          70 :     length = num_bonds + num_atoms + 1;
     711                 :          70 :     pp = (NEIGH_LIST*)inchi_calloc(((long long)num_atoms + 1), sizeof(NEIGH_LIST));
     712                 :          70 :     pAtList = (AT_NUMB*)inchi_malloc(length * sizeof(AT_NUMB));
     713   [ -  +  -  + ]:          70 :     if (pp && pAtList) /* djb-rwth: cast operator added; addressing LLVM warning */
     714                 :             :     {
     715                 :             :         /*  Create empty connection table */
     716         [ +  + ]:         702 :         for (i = 1, length = 0; i <= num_atoms; i++)
     717                 :             :         {
     718                 :         632 :             start = length;
     719                 :         632 :             length += ( valence[i] + 1 );
     720                 :         632 :             pp[i - 1] = pAtList + start;
     721                 :         632 :             pp[i - 1][0] = 0;
     722                 :             :         }
     723                 :             :         /*  Fill out the CT */
     724         [ +  + ]:        1219 :         for (i = 1, n_vertex = LinearCT[0] - 1; i < nLenCT; i++)
     725                 :             :         {
     726         [ +  + ]:        1149 :             if (( n_neigh = LinearCT[i] - 1 ) < n_vertex)
     727                 :             :             {
     728                 :             :                 /*  Vertex - neighbor connection */
     729                 :         587 :                 j = (int) ( ++pp[(int) n_vertex][0] );
     730                 :         587 :                 pp[(int) n_vertex][j] = n_neigh;
     731                 :             :                 /*  neighbor - vertex connection */
     732                 :         587 :                 j = (int) ( ++pp[(int) n_neigh][0] );
     733                 :         587 :                 pp[(int) n_neigh][j] = n_vertex;
     734                 :             :             }
     735                 :             :             else
     736                 :             :             {
     737         [ -  + ]:         562 :                 if ((int) ( n_vertex = n_neigh ) >= num_atoms)
     738                 :             :                 {
     739                 :           0 :                     goto exit_function;
     740                 :             :                 }
     741                 :             :             }
     742                 :             :         }
     743                 :          70 :         err = 0;
     744                 :             :     }
     745                 :             : 
     746                 :           0 : exit_function:
     747         [ +  - ]:          70 :     if (valence)
     748                 :             :     {
     749         [ +  - ]:          70 :         inchi_free( valence );
     750                 :             :     }
     751         [ -  + ]:          70 :     if (err) /* djb-rwth: ignoring LLVM warning */
     752                 :             :     {
     753         [ #  # ]:           0 :         if (pAtList)
     754                 :             :         {
     755         [ #  # ]:           0 :             inchi_free( pAtList );
     756                 :             :         }
     757         [ #  # ]:           0 :         if (pp)
     758                 :             :         {
     759         [ #  # ]:           0 :             inchi_free( pp );
     760                 :           0 :             pp = NULL;
     761                 :             :         }
     762                 :             :     }
     763                 :             : 
     764                 :          70 :     return pp; /* djb-rwth: ignoring LLVM warning: since a pointer is returned, memory should be freed in a function which calls *CreateNeighListFromLinearCT */
     765                 :             : }
     766                 :             : 
     767                 :             : 
     768                 :             : /****************************************************************************
     769                 :             :  NEIGH_LIST pp[] is an array of pointers to the lists of neighboring
     770                 :             :  atoms numbers. The first number in each list is a number of neighbors.
     771                 :             :  In case of bDoubleBondSquare != 0 neighbors connected by the double bond
     772                 :             :  appear 2 times. The first element pp[0] is a pointer to be deallocated
     773                 :             :  to free all the lists.
     774                 :             : ****************************************************************************/
     775                 :         502 : NEIGH_LIST *CreateNeighList( int num_atoms,
     776                 :             :                              int num_at_tg,
     777                 :             :                              sp_ATOM* at,
     778                 :             :                              int bDoubleBondSquare,
     779                 :             :                              T_GROUP_INFO *t_group_info )
     780                 :             : {
     781                 :             :     /*  +1 to add NULL termination */
     782                 :         502 :     NEIGH_LIST *pp = (NEIGH_LIST *) inchi_calloc( ( (long long)num_at_tg + 1 ), sizeof( NEIGH_LIST ) ); /* djb-rwth: cast operator added */
     783                 :         502 :     T_GROUP   *t_group = NULL;
     784                 :         502 :     AT_NUMB   *nEndpointAtomNumber = NULL;
     785                 :         502 :     int        num_t_groups = 0;
     786                 :             :     int        nFirstEndpointAtNoPos;
     787                 :             : 
     788                 :         502 :     AT_NUMB   *pAtList = NULL;
     789                 :             :     int        length, start, val, i, j;
     790         [ +  - ]:         502 :     if (pp)
     791                 :             :     {
     792         [ +  + ]:         502 :         if (num_at_tg > num_atoms)
     793                 :             :         {
     794                 :           7 :             t_group = t_group_info->t_group;
     795                 :           7 :             num_t_groups = t_group_info->num_t_groups;
     796                 :           7 :             nEndpointAtomNumber = t_group_info->nEndpointAtomNumber;
     797                 :             :         }
     798                 :             : 
     799         [ +  - ]:         502 :         if (!bDoubleBondSquare)
     800                 :             :         {
     801         [ +  + ]:        4681 :             for (i = 0, length = 0; i < num_atoms; i++)
     802                 :             :             {
     803   [ +  +  +  + ]:        4179 :                 length += (int) at[i].valence + ( num_t_groups && at[i].endpoint );
     804                 :             :             }
     805                 :         502 :             length += num_atoms;
     806         [ +  + ]:         514 :             for (i = 0; i < num_t_groups; i++)
     807                 :             :             {
     808                 :          12 :                 length += (int) t_group[i].nNumEndpoints;
     809                 :             :             }
     810                 :         502 :             length += num_t_groups;
     811                 :             :         }
     812                 :             :         else
     813                 :             :         {
     814         [ #  # ]:           0 :             for (i = 0, length = 0; i < num_atoms; i++)
     815                 :             :             {
     816                 :           0 :                 val = (int) at[i].valence;
     817         [ #  # ]:           0 :                 for (j = 0; j < val; j++)
     818                 :             :                 {
     819   [ #  #  #  # ]:           0 :                     length += 1 + ( bDoubleBondSquare && BOND_DOUBLE == at[i].bond_type[j] );
     820                 :             :                 }
     821   [ #  #  #  # ]:           0 :                 length += ( num_t_groups && at[i].endpoint );
     822                 :             :             }
     823                 :           0 :             length += num_atoms;
     824         [ #  # ]:           0 :             for (i = 0; i < num_t_groups; i++)
     825                 :             :             {
     826                 :           0 :                 length += (int) t_group[i].nNumEndpoints;
     827                 :             :             }
     828                 :           0 :             length += num_t_groups;
     829                 :             :         }
     830                 :         502 :         length++; /*  +1 to save number of neighbors */
     831                 :         502 :         pAtList = (AT_NUMB*)inchi_malloc(length * sizeof(AT_NUMB));
     832         [ +  - ]:         502 :         if (pAtList) /* djb-rwth: addressing LLVM warning */
     833                 :             :         {
     834         [ +  - ]:         502 :             if (!bDoubleBondSquare)
     835                 :             :             {
     836         [ +  + ]:        4681 :                 for (i = 0, length = 0; i < num_atoms; i++)
     837                 :             :                 {
     838                 :        4179 :                     val = at[i].valence;
     839                 :        4179 :                     start = length++;
     840         [ +  + ]:       11723 :                     for (j = 0; j < val; j++)
     841                 :             :                     {
     842                 :        7544 :                         pAtList[length++] = at[i].neighbor[j];
     843                 :             :                     }
     844                 :             :                     /*  add endpoint */
     845   [ +  +  +  + ]:        4179 :                     if (num_t_groups && at[i].endpoint)
     846                 :             :                     {
     847                 :          28 :                         pAtList[length++] = num_atoms + (int) at[i].endpoint - 1;
     848                 :             :                     }
     849                 :        4179 :                     pAtList[start] = length - start - 1;  /*  number of neighbors before the list of neighbors */
     850                 :        4179 :                     pp[i] = pAtList + start;              /*  pointer to the <num.neigh.><list of neigh> */
     851                 :             :                 }
     852                 :             :             }
     853                 :             :             else
     854                 :             :             {
     855         [ #  # ]:           0 :                 for (i = 0, length = 0; i < num_atoms; i++)
     856                 :             :                 {
     857                 :           0 :                     val = at[i].valence;
     858                 :           0 :                     start = length++;
     859         [ #  # ]:           0 :                     for (j = 0; j < val; j++)
     860                 :             :                     {
     861                 :           0 :                         pAtList[length++] = at[i].neighbor[j]; /* djb-rwth: buffer overrun avoided implicitly */
     862   [ #  #  #  # ]:           0 :                         if (bDoubleBondSquare && BOND_DOUBLE == at[i].bond_type[j])
     863                 :             :                         {
     864                 :           0 :                             pAtList[length++] = at[i].neighbor[j]; /*  a list of neighbor orig. numbers */
     865                 :             :                         }
     866                 :             :                     }
     867                 :             :                     /*  Add endpoint */
     868   [ #  #  #  # ]:           0 :                     if (num_t_groups && at[i].endpoint)
     869                 :             :                     {
     870                 :           0 :                         pAtList[length++] = num_atoms + (int) at[i].endpoint - 1;
     871                 :             :                     }
     872                 :           0 :                     pAtList[start] = length - start - 1;  /*  number of neighbors before the list of neighbors */
     873                 :           0 :                     pp[i] = pAtList + start;              /*  pointer to the <num.neigh.><list of neigh> */
     874                 :             :                 }
     875                 :             :             }
     876                 :             : 
     877                 :             :             /*  Add t-groups */
     878         [ +  + ]:         514 :             for (i = 0; i < num_t_groups; i++)
     879                 :             :             {
     880                 :          12 :                 val = (int) t_group[i].nNumEndpoints;
     881                 :          12 :                 start = length++;
     882                 :          12 :                 nFirstEndpointAtNoPos = (int) t_group[i].nFirstEndpointAtNoPos;
     883         [ +  + ]:          40 :                 for (j = 0; j < val; j++)
     884                 :             :                 {
     885                 :          28 :                     pAtList[length++] = nEndpointAtomNumber[nFirstEndpointAtNoPos + j];
     886                 :             :                 }
     887                 :          12 :                 pAtList[start] = length - start - 1;  /*  number of neighbors before the list of neighbors */
     888                 :          12 :                 pp[num_atoms + i] = pAtList + start;    /*  pointer to the <num.neigh.><list of neigh> */
     889                 :             :             }
     890                 :             :         }
     891                 :             :         else
     892                 :             :         {
     893         [ #  # ]:           0 :             inchi_free(pAtList); /* djb-rwth: fixing coverity ID #499598 */
     894         [ #  # ]:           0 :             inchi_free( pp );
     895                 :           0 :             return NULL;
     896                 :             :         }
     897                 :             :     } /* djb-rwth: ignoring LLVM warning */
     898                 :             : 
     899                 :             :     /* djb-rwth: fixing coverity ID #499598 -- pp uses pAtList values */
     900                 :             : 
     901                 :         502 :     return pp; /* djb-rwth: ignoring LLVM warning: since a pointer is returned, memory should be freed in a function which calls *CreateNeighList */
     902                 :             : }
     903                 :             : 
     904                 :             : 
     905                 :             : /****************************************************************************/
     906                 :        1363 : void FreeNeighList( NEIGH_LIST *pp )
     907                 :             : {
     908         [ +  + ]:        1363 :     if (pp)
     909                 :             :     {
     910         [ +  - ]:         572 :         if (pp[0])
     911                 :             :         {
     912         [ +  - ]:         572 :             inchi_free( pp[0] );
     913                 :             :         }
     914         [ +  - ]:         572 :         inchi_free( pp );
     915                 :             :     }
     916                 :             : 
     917                 :        1363 : }
     918                 :             : 
     919                 :             : 
     920                 :             : /****************************************************************************/
     921                 :         218 : int BreakAllTies( CANON_GLOBALS *pCG,
     922                 :             :                   int num_atoms,
     923                 :             :                   int num_max,
     924                 :             :                   AT_RANK **pRankStack,
     925                 :             :                   NEIGH_LIST *NeighList,
     926                 :             :                   AT_RANK *nTempRank,
     927                 :             :                   CANON_STAT *pCS )
     928                 :             : {
     929                 :         218 :     int i, nRet = -1, nNumRanks = 1 /* value does not matter*/;
     930                 :             : 
     931                 :         218 :     AT_RANK *nPrevRank = *pRankStack++;
     932                 :         218 :     AT_RANK *nPrevAtomNumber = *pRankStack++;
     933                 :             : 
     934                 :         218 :     AT_RANK *nNewRank = NULL;
     935                 :         218 :     AT_RANK *nNewAtomNumber = NULL;
     936                 :             : 
     937         [ +  + ]:         218 :     if (!pRankStack[0])
     938                 :             :     {
     939                 :          96 :         pRankStack[0] = (AT_RANK *) inchi_malloc( num_max * sizeof( *nNewRank ) );
     940                 :             :     }
     941         [ +  + ]:         218 :     if (!pRankStack[1])
     942                 :             :     {
     943                 :          96 :         pRankStack[1] = (AT_RANK *) inchi_malloc( num_max * sizeof( *nNewAtomNumber ) );
     944                 :             :     }
     945   [ +  -  -  + ]:         218 :     if (!pRankStack[0] || !pRankStack[1])
     946                 :             :     {
     947                 :           0 :         return CT_OUT_OF_RAM;  /*   <BRKPT> */
     948                 :             :     }
     949                 :         218 :     nNewRank = pRankStack[0];
     950                 :         218 :     nNewAtomNumber = pRankStack[1];
     951                 :             : 
     952   [ +  -  +  - ]:         218 :     if (nNewRank && nNewAtomNumber)
     953                 :             :     {
     954                 :         218 :         memcpy(nNewAtomNumber, nPrevAtomNumber, num_atoms * sizeof(nNewAtomNumber[0]));
     955                 :         218 :         memcpy(nNewRank, nPrevRank, num_atoms * sizeof(nNewRank[0]));
     956         [ +  + ]:        2224 :         for (i = 1, nRet = 0; i < num_atoms; i++)
     957                 :             :         {
     958                 :             :             /*  12-12-2001: replaced Prev... with New... */
     959         [ +  + ]:        2006 :             if (nNewRank[(int) nNewAtomNumber[i - 1]] == nNewRank[(int) nNewAtomNumber[i]])
     960                 :             :             {
     961                 :          58 :                 nNewRank[nNewAtomNumber[i - 1]] = (AT_RANK) i;
     962                 :          58 :                 nNumRanks = DifferentiateRanks2( pCG, num_atoms, NeighList,
     963                 :             :                                                  nNumRanks, nNewRank, nTempRank,
     964                 :             :                                                  nNewAtomNumber,
     965                 :             :                                                  &pCS->lNumNeighListIter, 1 );
     966                 :          58 :                 pCS->lNumBreakTies++;
     967                 :          58 :                 nRet++;
     968                 :             :             }
     969                 :             :         }
     970                 :             :     }
     971                 :             : 
     972                 :         218 :     return nRet;
     973                 :             : }
     974                 :             : 
     975                 :             : 
     976                 :             : /****************************************************************************
     977                 :             :  Int insertions sort
     978                 :             : ****************************************************************************/
     979                 :           2 : int * iisort( int *list, int num )
     980                 :             : {
     981                 :             :     int i;
     982         [ +  + ]:           6 :     for (i = 1; i < num; i++)
     983                 :             :     {
     984                 :           4 :         int tmp = list[i];
     985                 :           4 :         int j = i - 1;
     986   [ +  +  +  + ]:           6 :         while (j >= 0 && list[j] > tmp)
     987                 :             :         {
     988                 :           2 :             list[j + 1] = list[j];
     989                 :           2 :             j--;
     990                 :             :         }
     991                 :           4 :         list[j + 1] = tmp;
     992                 :             :     }
     993                 :             : 
     994                 :           2 :     return list;
     995                 :             : }
        

Generated by: LCOV version 2.0-1