LCOV - code coverage report
Current view: top level - src - ichican2.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 62.4 % 2127 1327
Test Date: 2026-10-14 12:14:55 Functions: 79.3 % 58 46
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 42.0 % 1834 770

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * SPDX-License-Identifier: MIT
       3                 :             :  * Copyright (c) 2024 IUPAC and InChI Trust
       4                 :             :  */
       5                 :             : 
       6                 :             : 
       7                 :             : /* #define CHECK_WIN32_VC_HEAP */
       8                 :             : 
       9                 :             : #include <stdlib.h>
      10                 :             : #include <string.h>
      11                 :             : #include <limits.h>
      12                 :             : #include <time.h>
      13                 :             : 
      14                 :             : 
      15                 :             : #include "mode.h"
      16                 :             : #include "ichicano.h"
      17                 :             : 
      18                 :             : #include "ichicomn.h"
      19                 :             : #include "ichitime.h"
      20                 :             : 
      21                 :             : #include "bcf_s.h"
      22                 :             : 
      23                 :             : #define MAX_CELLS    32766
      24                 :             : #define MAX_NODES    32766
      25                 :             : #define MAX_SET_SIZE 32766 /*16384*/
      26                 :             : #define NORMALLY_ALLOWED_MAX_SET_SIZE 2048
      27                 :             : #define MAX_LAYERS   100
      28                 :             : 
      29                 :             : #define SEPARATE_CANON_CALLS 0
      30                 :             : 
      31                 :             : #define INCHI_CANON_INFINITY       0x7FFF
      32                 :             : 
      33                 :             : #define INCHI_CANON_MIN
      34                 :             : 
      35                 :             : #define EMPTY_CT       0
      36                 :             : #define EMPTY_H_NUMBER (INCHI_CANON_INFINITY-1)
      37                 :             : #define BASE_H_NUMBER  ((INCHI_CANON_INFINITY-1)/2)
      38                 :             : #define EMPTY_ISO_SORT_KEY LONG_MAX
      39                 :             : 
      40                 :             : 
      41                 :             : /*
      42                 :             : #define INCHI_CANON_USE_HASH
      43                 :             : */ /* djb-rwth: constant has not been defined? */
      44                 :             : #ifdef INCHI_CANON_USE_HASH
      45                 :             : typedef unsigned long  U_INT_32;
      46                 :             : typedef unsigned char  U_INT_08;
      47                 :             : typedef U_INT_32       CtHash;
      48                 :             : CtHash hash_mark_bit;
      49                 :             : #endif
      50                 :             : 
      51                 :             : /* -- moved to ichi_bns.h --
      52                 :             : typedef U_SHORT  bitWord;
      53                 :             : #define BIT_WORD_MASK  ((bitWord)~0)
      54                 :             : */
      55                 :             : 
      56                 :             : /*bitWord      mark_bit; */    /* highest bit in AT_NUMB */
      57                 :             : /*bitWord      mask_bit; */    /* ~mark_bit */
      58                 :             : 
      59                 :             : static AT_NUMB       rank_mark_bit;
      60                 :             : static AT_NUMB       rank_mask_bit;
      61                 :             : 
      62                 :             : 
      63                 :             : typedef AT_NUMB    Node;
      64                 :             : typedef NEIGH_LIST Graph;
      65                 :             : 
      66                 :             : /*
      67                 :             : typedef struct tagGraph
      68                 :             : {
      69                 :             :     int dummy;
      70                 :             : }
      71                 :             : Graph;
      72                 :             : */
      73                 :             : 
      74                 :             : typedef struct tagUnorderedPartition
      75                 :             : {
      76                 :             :     /* AT_NUMB *next; */ /* links */
      77                 :             :     AT_NUMB *equ2; /* mcr */
      78                 :             : } UnorderedPartition;
      79                 :             : 
      80                 :             : typedef struct tagCell
      81                 :             : {
      82                 :             :     int       first; /* index of the first cell element in Partition::AtNumber[] */
      83                 :             :     int       next;   /* next after the last index */
      84                 :             :     int       prev;   /* position of the previously returned cell element */
      85                 :             : } Cell;
      86                 :             : 
      87                 :             : #ifdef NEVER /* moved to ichi_bns.h */
      88                 :             : typedef struct tagNodeSet {
      89                 :             :     bitWord **bitword;
      90                 :             :     int num_set; /* number of sets */
      91                 :             :     int len_set; /* number of bitWords in each set */
      92                 :             : } NodeSet;
      93                 :             : #endif
      94                 :             : 
      95                 :             : typedef struct tagTransposition
      96                 :             : {
      97                 :             :     AT_NUMB *nAtNumb;
      98                 :             : } Transposition;
      99                 :             : 
     100                 :             : 
     101                 :             : typedef struct tagCTable
     102                 :             : {
     103                 :             :     AT_RANK  *Ctbl;     /* connection table */
     104                 :             :     /* Format-atoms:   atom_rank[k] neigh_rank[k][1]...neigh_rank[k][n]
     105                 :             :                        1) atom_rank[k1] < atom_rank[k2]  <=> k1 < k2
     106                 :             :               where    2) atom_rank[k] > neigh_rank[k][i], i=1..n
     107                 :             :                        3) neigh_rank[k][i] < neigh_rank[k][j]  <=>  i < j
     108                 :             : 
     109                 :             :        Format-tgroup:  tgroup_rank[k] endpoint_rank[k][1]...endpoint_rank[k][n]
     110                 :             :               where    1) tgroup_rank[k1] < tgroup_rank[k2] <=> k1 < k2
     111                 :             :                        2) endpoint_rank[k][i] < endpoint_rank[k][j] <=> i < j
     112                 :             : 
     113                 :             :               Note:    tgroup_rank[k] > endpoint_rank[k][j] for all j by construction
     114                 :             :     */
     115                 :             : 
     116                 :             :     int       lenCt;        /* used length */
     117                 :             :     int       nLenCTAtOnly; /* to split Ctnl comparison in case of bDigraph != 0 */
     118                 :             :     int       maxlenCt;     /* allocated length of Ctbl */
     119                 :             :     int       maxPos;       /* allocated length of nextCtblPos */
     120                 :             :     int       maxVert;      /* max number of vertices to separate atoms from taut groups */
     121                 :             :     int       lenPos;       /* first unused element of nextCtblPos */
     122                 :             :     AT_RANK  *nextAtRank;   /* rank (k value) after the last node of the Ctbl portion*/
     123                 :             :     AT_NUMB  *nextCtblPos;  /* first unused element of Ctbl */
     124                 :             : 
     125                 :             :     /* hydrogen atoms fixed in tautomeric representation:
     126                 :             :        compare before diff sign inversion: (+) <=> Ct1->() > Ct2->() */
     127                 :             :     NUM_H          *NumH;
     128                 :             :     int             lenNumH;    /* used length */
     129                 :             :     int             maxlenNumH; /*  n + T_NUM_NO_ISOTOPIC*(n_tg-n) + 1 */
     130                 :             : 
     131                 :             :     /* hydrogen atoms fixed in non-tautomeric representation only:
     132                 :             :        compare before diff sign inversion: (+) <=> Ct1->() > Ct2->() */
     133                 :             :     NUM_H           *NumHfixed;
     134                 :             :     /*int              lenNumHfixed;    */   /* used length */
     135                 :             :     /*int              maxlenNumHfixed; */   /* max length = n+1  */
     136                 :             : 
     137                 :             :     /* isotopic atoms (without tautomeric H) and isotopic tautomeric groups */
     138                 :             :     /* note: AT_ISO_SORT_KEY and T_GROUP_ISOWT are identical types: long    */
     139                 :             :     AT_ISO_SORT_KEY *iso_sort_key;
     140                 :             :     int              len_iso_sort_key;    /* used length */
     141                 :             :     int              maxlen_iso_sort_key; /* max length = n_tg+1 */
     142                 :             : 
     143                 :             :     S_CHAR          *iso_exchg_atnos;
     144                 :             :     int              len_iso_exchg_atnos;
     145                 :             :     int              maxlen_iso_exchg_atnos;
     146                 :             : 
     147                 :             :     /* isotopic hydrogen atoms fixed in non-tautomeric representation only */
     148                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
     149                 :             :     AT_ISO_SORT_KEY *iso_sort_key_Hfixed;
     150                 :             :     int              len_iso_sort_key_Hfixed;    /* used length */
     151                 :             :     int              maxlen_iso_sort_key_Hfixed; /* max length = n+1  */
     152                 :             : #endif
     153                 :             : 
     154                 :             : #ifdef INCHI_CANON_USE_HASH
     155                 :             :     CtHash   *hash;
     156                 :             : #endif
     157                 :             : } ConTable;
     158                 :             : 
     159                 :             : 
     160                 :             : 
     161                 :             : /****************************************************************************/
     162                 :             : 
     163                 :             : 
     164                 :             : typedef struct tagkLeast
     165                 :             : {
     166                 :             :     int k;
     167                 :             :     int i;
     168                 :             : } kLeast;
     169                 :             : 
     170                 :             : 
     171                 :             : 
     172                 :             : /************* local prototypes **********************************/
     173                 :             : struct tagINCHI_CLOCK;
     174                 :             : int CanonGraph( struct tagINCHI_CLOCK *ic,
     175                 :             :                 CANON_GLOBALS *pCG,
     176                 :             :                 int n,
     177                 :             :                 int n_tg,
     178                 :             :                 int n_max,
     179                 :             :                 int bDigraph,
     180                 :             :                 Graph *G,
     181                 :             :                 Partition pi[],
     182                 :             :                 AT_RANK *nSymmRank,
     183                 :             :                 AT_RANK *nCanonRank,
     184                 :             :                 AT_NUMB *nAtomNumberCanon,
     185                 :             :                 CANON_DATA *pCD,
     186                 :             :                 CANON_COUNTS *pCC,
     187                 :             :                 ConTable **pp_zb_rho_inp,
     188                 :             :                 ConTable **pp_zb_rho_out,
     189                 :             :                 int LargeMolecules );
     190                 :             : 
     191                 :             : void CtPartFill( Graph *G, CANON_DATA *pCD, Partition *p,
     192                 :             :                  ConTable *Ct, int k, int n, int n_tg, int n_max );
     193                 :             : 
     194                 :             : void CtPartClear( ConTable *Ct, int k );
     195                 :             : 
     196                 :             : void CtPartINCHI_CANON_INFINITY( ConTable *Ct, S_CHAR *cmp, int k );
     197                 :             : 
     198                 :             : int CtPartCompare( ConTable *Ct1, ConTable *Ct2, S_CHAR *cmp,
     199                 :             :                    kLeast *kLeastForLayer, int k, int bOnlyCommon, int bSplitTautCompare );
     200                 :             : 
     201                 :             : int CtFullCompare( ConTable *Ct1, ConTable *Ct2, int bOnlyCommon, int bSplitTautCompare );
     202                 :             : 
     203                 :             : void CtPartCopy( ConTable *Ct1 /* to */, ConTable *Ct2 /* from */, int k );
     204                 :             : 
     205                 :             : void CtFullCopy( ConTable *Ct1, ConTable *Ct2 );
     206                 :             : 
     207                 :             : int CtFullCompareLayers( kLeast *kLeastForLayer );
     208                 :             : 
     209                 :             : int CtCompareLayersGetFirstDiff( kLeast *kLeast_rho, int nOneAdditionalLayer,
     210                 :             :                                  int *L_rho, int *I_rho, int *k_rho );
     211                 :             : 
     212                 :             : int CtPartCompareLayers( kLeast *kLeast_rho, int L_rho_fix_prev, int nOneAdditionalLayer );
     213                 :             : 
     214                 :             : void UpdateCompareLayers( kLeast kLeastForLayer[], int hzz );
     215                 :             : 
     216                 :             : int GetOneAdditionalLayer( CANON_DATA *pCD, ConTable *pzb_rho_fix );
     217                 :             : 
     218                 :             : void CleanNumH( NUM_H *NumH, int len );
     219                 :             : 
     220                 :             : int CleanCt( AT_RANK *Ct, int len );
     221                 :             : 
     222                 :             : void CleanIsoSortKeys( AT_ISO_SORT_KEY * isk, int len );
     223                 :             : 
     224                 :             : void MergeCleanIsoSortKeys( AT_ISO_SORT_KEY * isk1, AT_ISO_SORT_KEY * isk2, int len );
     225                 :             : 
     226                 :             : int  UnorderedPartitionJoin( UnorderedPartition *p1, UnorderedPartition *p2, int n );
     227                 :             : 
     228                 :             : Node GetUnorderedPartitionMcrNode( UnorderedPartition *p1, Node v );
     229                 :             : 
     230                 :             : int  nJoin2Mcrs2( AT_RANK *nEqArray, AT_RANK n1, AT_RANK n2 );
     231                 :             : 
     232                 :             : AT_RANK nGetMcr2( AT_RANK *nEqArray, AT_RANK n );
     233                 :             : 
     234                 :             : int  AllNodesAreInSet( NodeSet *cur_nodes, int lcur_nodes, NodeSet *set, int lset );
     235                 :             : 
     236                 :             : void NodeSetFromVertices( CANON_GLOBALS *pCG, NodeSet *cur_nodes, int l, Node *v, int num_v );
     237                 :             : 
     238                 :             : void CellMakeEmpty( Cell *baseW, int k );
     239                 :             : 
     240                 :             : Node CellGetMinNode( Partition *p, Cell *W, Node v, CANON_DATA *pCD );
     241                 :             : 
     242                 :             : int  CellGetNumberOfNodes( Partition *p, Cell *W );
     243                 :             : 
     244                 :             : int  CellIntersectWithSet( struct tagCANON_GLOBALS *pCG, Partition *p, Cell *W, NodeSet *Mcr, int l );
     245                 :             : 
     246                 :             : int  PartitionColorVertex( CANON_GLOBALS *pCG, Graph *G, Partition *p, Node v, int n, int n_tg, int n_max, int bDigraph, int nNumPrevRanks );
     247                 :             : 
     248                 :             : void PartitionCopy( Partition *To, Partition *From, int n );
     249                 :             : 
     250                 :             : int  PartitionSatisfiesLemma_2_25( Partition *p, int n );
     251                 :             : 
     252                 :             : void PartitionGetTransposition( Partition *pFrom, Partition *pTo, int n, Transposition *gamma );
     253                 :             : 
     254                 :             : void PartitionGetMcrAndFixSet( CANON_GLOBALS *pCG,
     255                 :             :                                Partition *p,
     256                 :             :                                NodeSet *Mcr,
     257                 :             :                                NodeSet *Fix,
     258                 :             :                                int n,
     259                 :             :                                int l );
     260                 :             : 
     261                 :             : int  PartitionGetFirstCell( Partition *p, Cell *baseW, int k, int n );
     262                 :             : 
     263                 :             : int  PartitionIsDiscrete( Partition *p, int n );
     264                 :             : 
     265                 :             : void PartitionFree( Partition *p );
     266                 :             : 
     267                 :             : int  PartitionCreate( Partition *p, int n );
     268                 :             : 
     269                 :             : void UnorderedPartitionMakeDiscrete( UnorderedPartition *p, int n );
     270                 :             : 
     271                 :             : void UnorderedPartitionFree( UnorderedPartition *p );
     272                 :             : 
     273                 :             : int  UnorderedPartitionCreate( UnorderedPartition *p, int n );
     274                 :             : 
     275                 :             : void CTableFree( ConTable *Ct );
     276                 :             : 
     277                 :             : int  CTableCreate( ConTable *Ct, int n, CANON_DATA *pCD );
     278                 :             : 
     279                 :             : void TranspositionFree( Transposition *p );
     280                 :             : 
     281                 :             : int  TranspositionCreate( Transposition *p, int n );
     282                 :             : 
     283                 :             : void TranspositionGetMcrAndFixSetAndUnorderedPartition( struct tagCANON_GLOBALS *pCG, Transposition *gamma, NodeSet *McrSet, NodeSet *FixSet, int n, int l, UnorderedPartition *p );
     284                 :             : 
     285                 :             : void insertions_sort_NeighList_AT_NUMBERS2( NEIGH_LIST base, AT_RANK *nRank, AT_RANK max_rj );
     286                 :             : 
     287                 :             : int  WriteGraph( Graph *G, int n, int gnum, char *fname, char *fmode );
     288                 :             : 
     289                 :             : int  SetInitialRanks2( int num_atoms,
     290                 :             :                        ATOM_INVARIANT2* pAtomInvariant2,
     291                 :             :                        AT_RANK *nNewRank,
     292                 :             :                        AT_RANK *nAtomNumber,
     293                 :             :                        CANON_GLOBALS *pCG );
     294                 :             : 
     295                 :             : void FillOutAtomInvariant2( sp_ATOM* at, int num_atoms, int num_at_tg, ATOM_INVARIANT2* pAtomInvariant,
     296                 :             :                            int bIgnoreIsotopic, int bHydrogensInRanks, int bHydrogensFixedInRanks,
     297                 :             :                            int bDigraph, int bTautGroupsOnly, T_GROUP_INFO *t_group_info );
     298                 :             : 
     299                 :             : int  GetCanonRanking2( int num_atoms, int num_at_tg, int num_max, int bDigraph, sp_ATOM* at,
     300                 :             :                      AT_RANK **pRankStack, int nNumPrevRanks,
     301                 :             :                      AT_RANK *nSymmRank, AT_RANK *nCanonRank,
     302                 :             :                      NEIGH_LIST *NeighList, AT_RANK *nTempRank,
     303                 :             :                      CANON_STAT* pCS );
     304                 :             : 
     305                 :             : 
     306                 :             : #if ( SEPARATE_CANON_CALLS == 1 )
     307                 :             : 
     308                 :             : 
     309                 :             : /* for profiling purposes */
     310                 :             : 
     311                 :             : 
     312                 :             : /****************************************************************************/
     313                 :             : int CanonGraph01( int n,
     314                 :             :                   int n_tg,
     315                 :             :                   int n_max,
     316                 :             :                   int bDigraph,
     317                 :             :                   Graph *G,
     318                 :             :                   Partition pi[],
     319                 :             :                   AT_RANK *nSymmRank,
     320                 :             :                   AT_RANK *nCanonRank,
     321                 :             :                   AT_NUMB *nAtomNumberCanon,
     322                 :             :                   CANON_DATA *pCD,
     323                 :             :                   CANON_COUNTS *pCC,
     324                 :             :                   ConTable **pp_zb_rho_inp,
     325                 :             :                   ConTable **pp_zb_rho_out,
     326                 :             :                   int LargeMolecules )
     327                 :             : {
     328                 :             :     return
     329                 :             :         CanonGraph( n, n_tg, n_max, bDigraph, G, pi,
     330                 :             :                     nSymmRank, nCanonRank, nAtomNumberCanon,
     331                 :             :                     pCD, pCC, pp_zb_rho_inp, pp_zb_rho_out,
     332                 :             :                     LargeMolecules );
     333                 :             : }
     334                 :             : 
     335                 :             : /****************************************************************************/
     336                 :             : int CanonGraph02( int n,
     337                 :             :                   int n_tg,
     338                 :             :                   int n_max,
     339                 :             :                   int bDigraph,
     340                 :             :                   Graph *G,
     341                 :             :                   Partition pi[],
     342                 :             :                   AT_RANK *nSymmRank,
     343                 :             :                   AT_RANK *nCanonRank,
     344                 :             :                   AT_NUMB *nAtomNumberCanon,
     345                 :             :                   CANON_DATA *pCD,
     346                 :             :                   CANON_COUNTS *pCC,
     347                 :             :                   ConTable **pp_zb_rho_inp,
     348                 :             :                   ConTable **pp_zb_rho_out,
     349                 :             :                   int LargeMolecules )
     350                 :             : {
     351                 :             :     return
     352                 :             :         CanonGraph( n, n_tg, n_max, bDigraph, G, pi,
     353                 :             :                     nSymmRank, nCanonRank, nAtomNumberCanon,
     354                 :             :                     pCD, pCC,
     355                 :             :                     pp_zb_rho_inp, pp_zb_rho_out );
     356                 :             : }
     357                 :             : 
     358                 :             : 
     359                 :             : /****************************************************************************/
     360                 :             : int CanonGraph03( int n,
     361                 :             :                   int n_tg,
     362                 :             :                   int n_max,
     363                 :             :                   int bDigraph,
     364                 :             :                   Graph *G, Partition pi[],
     365                 :             :                   AT_RANK *nSymmRank,
     366                 :             :                   AT_RANK *nCanonRank,
     367                 :             :                   AT_NUMB *nAtomNumberCanon,
     368                 :             :                   CANON_DATA *pCD,
     369                 :             :                   CANON_COUNTS *pCC,
     370                 :             :                   ConTable **pp_zb_rho_inp,
     371                 :             :                   ConTable **pp_zb_rho_out,
     372                 :             :                   int LargeMolecules )
     373                 :             : {
     374                 :             :     return
     375                 :             :         CanonGraph( n, n_tg, n_max, bDigraph, G, pi,
     376                 :             :                     nSymmRank, nCanonRank, nAtomNumberCanon,
     377                 :             :                     pCD, pCC,
     378                 :             :                     pp_zb_rho_inp, pp_zb_rho_out );
     379                 :             : }
     380                 :             : 
     381                 :             : 
     382                 :             : /****************************************************************************/
     383                 :             : int CanonGraph04( int n,
     384                 :             :                   int n_tg,
     385                 :             :                   int n_max,
     386                 :             :                   int bDigraph,
     387                 :             :                   Graph *G,
     388                 :             :                   Partition pi[],
     389                 :             :                   AT_RANK *nSymmRank,
     390                 :             :                   AT_RANK *nCanonRank,
     391                 :             :                   AT_NUMB *nAtomNumberCanon,
     392                 :             :                   CANON_DATA *pCD,
     393                 :             :                   CANON_COUNTS *pCC,
     394                 :             :                   ConTable **pp_zb_rho_inp,
     395                 :             :                   ConTable **pp_zb_rho_out,
     396                 :             :                   int LargeMolecules )
     397                 :             : {
     398                 :             :     return
     399                 :             :         CanonGraph( n, n_tg, n_max, bDigraph, G, pi,
     400                 :             :                     nSymmRank, nCanonRank, nAtomNumberCanon,
     401                 :             :                     pCD, pCC,
     402                 :             :                     pp_zb_rho_inp, pp_zb_rho_out );
     403                 :             : }
     404                 :             : 
     405                 :             : 
     406                 :             : /****************************************************************************/
     407                 :             : int CanonGraph05( int n,
     408                 :             :                   int n_tg,
     409                 :             :                   int n_max,
     410                 :             :                   int bDigraph,
     411                 :             :                   Graph *G,
     412                 :             :                   Partition pi[],
     413                 :             :                   AT_RANK *nSymmRank,
     414                 :             :                   AT_RANK *nCanonRank,
     415                 :             :                   AT_NUMB *nAtomNumberCanon,
     416                 :             :                   CANON_DATA *pCD,
     417                 :             :                   CANON_COUNTS *pCC,
     418                 :             :                   ConTable **pp_zb_rho_inp,
     419                 :             :                   ConTable **pp_zb_rho_out,
     420                 :             :                   int LargeMolecules )
     421                 :             : {
     422                 :             :     return
     423                 :             :         CanonGraph( n, n_tg, n_max, bDigraph, G, pi,
     424                 :             :                     nSymmRank, nCanonRank, nAtomNumberCanon,
     425                 :             :                     pCD, pCC,
     426                 :             :                     pp_zb_rho_inp, pp_zb_rho_out );
     427                 :             : }
     428                 :             : 
     429                 :             : 
     430                 :             : /****************************************************************************/
     431                 :             : int CanonGraph06( int n,
     432                 :             :                   int n_tg,
     433                 :             :                   int n_max,
     434                 :             :                   int bDigraph,
     435                 :             :                   Graph *G,
     436                 :             :                   Partition pi[],
     437                 :             :                   AT_RANK *nSymmRank,
     438                 :             :                   AT_RANK *nCanonRank,
     439                 :             :                   AT_NUMB *nAtomNumberCanon,
     440                 :             :                   CANON_DATA *pCD,
     441                 :             :                   CANON_COUNTS *pCC,
     442                 :             :                   ConTable **pp_zb_rho_inp,
     443                 :             :                   ConTable **pp_zb_rho_out,
     444                 :             :                   int LargeMolecules )
     445                 :             : {
     446                 :             :     return
     447                 :             :         CanonGraph( n, n_tg, n_max, bDigraph, G, pi,
     448                 :             :                     nSymmRank, nCanonRank, nAtomNumberCanon,
     449                 :             :                     pCD, pCC,
     450                 :             :                     pp_zb_rho_inp, pp_zb_rho_out );
     451                 :             : }
     452                 :             : 
     453                 :             : 
     454                 :             : /****************************************************************************/
     455                 :             : int CanonGraph07( int n,
     456                 :             :                   int n_tg,
     457                 :             :                   int n_max,
     458                 :             :                   int bDigraph,
     459                 :             :                   Graph *G,
     460                 :             :                   Partition pi[],
     461                 :             :                   AT_RANK *nSymmRank,
     462                 :             :                   AT_RANK *nCanonRank,
     463                 :             :                   AT_NUMB *nAtomNumberCanon,
     464                 :             :                   CANON_DATA *pCD,
     465                 :             :                   CANON_COUNTS *pCC,
     466                 :             :                   ConTable **pp_zb_rho_inp,
     467                 :             :                   ConTable **pp_zb_rho_out,
     468                 :             :                   int LargeMolecules )
     469                 :             : {
     470                 :             :     return
     471                 :             :         CanonGraph( n, n_tg, n_max, bDigraph, G, pi,
     472                 :             :                     nSymmRank, nCanonRank, nAtomNumberCanon,
     473                 :             :                     pCD, pCC,
     474                 :             :                     pp_zb_rho_inp, pp_zb_rho_out );
     475                 :             : }
     476                 :             : 
     477                 :             : 
     478                 :             : /****************************************************************************/
     479                 :             : int CanonGraph08( int n,
     480                 :             :                   int n_tg,
     481                 :             :                   int n_max,
     482                 :             :                   int bDigraph,
     483                 :             :                   Graph *G,
     484                 :             :                   Partition pi[],
     485                 :             :                   AT_RANK *nSymmRank,
     486                 :             :                   AT_RANK *nCanonRank,
     487                 :             :                   AT_NUMB *nAtomNumberCanon,
     488                 :             :                   CANON_DATA *pCD,
     489                 :             :                   CANON_COUNTS *pCC,
     490                 :             :                   ConTable **pp_zb_rho_inp,
     491                 :             :                   ConTable **pp_zb_rho_out,
     492                 :             :                   int LargeMolecules )
     493                 :             : {
     494                 :             :     return
     495                 :             :         CanonGraph( n, n_tg, n_max, bDigraph, G, pi,
     496                 :             :                     nSymmRank, nCanonRank, nAtomNumberCanon,
     497                 :             :                     pCD, pCC,
     498                 :             :                     pp_zb_rho_inp, pp_zb_rho_out );
     499                 :             : }
     500                 :             : 
     501                 :             : 
     502                 :             : /****************************************************************************/
     503                 :             : int CanonGraph09( int n,
     504                 :             :                   int n_tg,
     505                 :             :                   int n_max,
     506                 :             :                   int bDigraph,
     507                 :             :                   Graph *G,
     508                 :             :                   Partition pi[],
     509                 :             :                   AT_RANK *nSymmRank,
     510                 :             :                   AT_RANK *nCanonRank,
     511                 :             :                   AT_NUMB *nAtomNumberCanon,
     512                 :             :                   CANON_DATA *pCD,
     513                 :             :                   CANON_COUNTS *pCC,
     514                 :             :                   ConTable **pp_zb_rho_inp,
     515                 :             :                   ConTable **pp_zb_rho_out,
     516                 :             :                   int LargeMolecules )
     517                 :             : {
     518                 :             :     return
     519                 :             :         CanonGraph( n, n_tg, n_max, bDigraph, G, pi,
     520                 :             :                     nSymmRank, nCanonRank, nAtomNumberCanon,
     521                 :             :                     pCD, pCC,
     522                 :             :                     pp_zb_rho_inp, pp_zb_rho_out );
     523                 :             : }
     524                 :             : 
     525                 :             : 
     526                 :             : /****************************************************************************/
     527                 :             : int CanonGraph10( int n,
     528                 :             :                   int n_tg,
     529                 :             :                   int n_max,
     530                 :             :                   int bDigraph,
     531                 :             :                   Graph *G,
     532                 :             :                   Partition pi[],
     533                 :             :                   AT_RANK *nSymmRank,
     534                 :             :                   AT_RANK *nCanonRank,
     535                 :             :                   AT_NUMB *nAtomNumberCanon,
     536                 :             :                   CANON_DATA *pCD,
     537                 :             :                   CANON_COUNTS *pCC,
     538                 :             :                   ConTable **pp_zb_rho_inp,
     539                 :             :                   ConTable **pp_zb_rho_out,
     540                 :             :                   int LargeMolecules )
     541                 :             : {
     542                 :             :     return
     543                 :             :         CanonGraph( n, n_tg, n_max, bDigraph, G, pi,
     544                 :             :                     nSymmRank, nCanonRank, nAtomNumberCanon,
     545                 :             :                     pCD, pCC,
     546                 :             :                     pp_zb_rho_inp, pp_zb_rho_out );
     547                 :             : }
     548                 :             : 
     549                 :             : 
     550                 :             : /****************************************************************************/
     551                 :             : int CanonGraph11( int n,
     552                 :             :                   int n_tg,
     553                 :             :                   int n_max,
     554                 :             :                   int bDigraph,
     555                 :             :                   Graph *G,
     556                 :             :                   Partition pi[],
     557                 :             :                   AT_RANK *nSymmRank,
     558                 :             :                   AT_RANK *nCanonRank,
     559                 :             :                   AT_NUMB *nAtomNumberCanon,
     560                 :             :                   CANON_DATA *pCD,
     561                 :             :                   CANON_COUNTS *pCC,
     562                 :             :                   ConTable **pp_zb_rho_inp,
     563                 :             :                   ConTable **pp_zb_rho_out,
     564                 :             :                   int LargeMolecules )
     565                 :             : {
     566                 :             :     return
     567                 :             :         CanonGraph( n, n_tg, n_max, bDigraph, G, pi,
     568                 :             :                     nSymmRank, nCanonRank, nAtomNumberCanon,
     569                 :             :                     pCD, pCC,
     570                 :             :                     pp_zb_rho_inp, pp_zb_rho_out );
     571                 :             : }
     572                 :             : 
     573                 :             : 
     574                 :             : /****************************************************************************/
     575                 :             : int CanonGraph12( int n,
     576                 :             :                   int n_tg,
     577                 :             :                   int n_max,
     578                 :             :                   int bDigraph,
     579                 :             :                   Graph *G,
     580                 :             :                   Partition pi[],
     581                 :             :                   AT_RANK *nSymmRank,
     582                 :             :                   AT_RANK *nCanonRank,
     583                 :             :                   AT_NUMB *nAtomNumberCanon,
     584                 :             :                   CANON_DATA *pCD,
     585                 :             :                   CANON_COUNTS *pCC,
     586                 :             :                   ConTable **pp_zb_rho_inp,
     587                 :             :                   ConTable **pp_zb_rho_out,
     588                 :             :                   int LargeMolecules )
     589                 :             : {
     590                 :             :     return
     591                 :             :         CanonGraph( n, n_tg, n_max, bDigraph, G, pi,
     592                 :             :                     nSymmRank, nCanonRank, nAtomNumberCanon,
     593                 :             :                     pCD, pCC,
     594                 :             :                     pp_zb_rho_inp, pp_zb_rho_out, LargeMolecules );
     595                 :             : }
     596                 :             : #else
     597                 :             : 
     598                 :             : #define CanonGraph01 CanonGraph
     599                 :             : #define CanonGraph02 CanonGraph
     600                 :             : #define CanonGraph03 CanonGraph
     601                 :             : #define CanonGraph04 CanonGraph
     602                 :             : #define CanonGraph05 CanonGraph
     603                 :             : #define CanonGraph06 CanonGraph
     604                 :             : #define CanonGraph07 CanonGraph
     605                 :             : #define CanonGraph08 CanonGraph
     606                 :             : #define CanonGraph09 CanonGraph
     607                 :             : #define CanonGraph10 CanonGraph
     608                 :             : #define CanonGraph11 CanonGraph
     609                 :             : #define CanonGraph12 CanonGraph
     610                 :             : 
     611                 :             : #endif
     612                 :             : 
     613                 :             : 
     614                 :             : #ifdef INCHI_CANON_USE_HASH
     615                 :             : 
     616                 :             : 
     617                 :             : static call_fill_crc32_data = 1;
     618                 :             : static const U_INT_32 crc32_data[256];
     619                 :             : 
     620                 :             : 
     621                 :             : /****************************************************************************/
     622                 :             : void fill_crc32_data( )
     623                 :             : {
     624                 :             :     U_INT_32 c;
     625                 :             :     int n, k;
     626                 :             : 
     627                 :             :     for (n = 0; n < 256; n++)
     628                 :             :     {
     629                 :             :         c = (U_INT_32) n;
     630                 :             :         for (k = 0; k < 8; k++)
     631                 :             :         {
     632                 :             :             c = c & 1 ? 0xEDB88320L ^ ( c >> 1 ) : c >> 1;
     633                 :             :         }
     634                 :             :         crc32_data[n] = c;
     635                 :             :     }
     636                 :             :     call_fill_crc32_data = 0;
     637                 :             : }
     638                 :             : 
     639                 :             : 
     640                 :             : /****************************************************************************/
     641                 :             : unsigned long add2crc32( unsigned long crc32, AT_NUMB n )
     642                 :             : {
     643                 :             :     U_INT_08 chr;
     644                 :             :     if (call_fill_crc32_data)
     645                 :             :     {
     646                 :             :         fill_crc32_data( );
     647                 :             :     }
     648                 :             :     chr = n % 128;
     649                 :             :     crc32 = crc32_data[( (int) crc32 ^ (int) chr ) & 0xff] ^ ( crc32 >> 8 );
     650                 :             :     chr = n / 128;
     651                 :             :     crc32 = crc32_data[( (int) crc32 ^ (int) chr ) & 0xff] ^ ( crc32 >> 8 );
     652                 :             :     return crc32;
     653                 :             : }
     654                 :             : #endif
     655                 :             : 
     656                 :             : 
     657                 :             : 
     658                 :             : /****************************************************************************/
     659                 :         175 : int TranspositionCreate( Transposition *p, int n )
     660                 :             : {
     661                 :         175 :     p->nAtNumb = (AT_NUMB*) inchi_calloc( n, sizeof( p->nAtNumb[0] ) );
     662         [ +  - ]:         175 :     if (p->nAtNumb)
     663                 :             :     {
     664                 :         175 :         return 1;
     665                 :             :     }
     666                 :             : 
     667                 :           0 :     return 0;
     668                 :             : }
     669                 :             : 
     670                 :             : 
     671                 :             : /****************************************************************************/
     672                 :         175 : void TranspositionFree( Transposition *p )
     673                 :             : {
     674   [ +  -  +  - ]:         175 :     if (p && p->nAtNumb)
     675                 :             :     {
     676         [ +  - ]:         175 :         inchi_free( p->nAtNumb );
     677                 :         175 :         p->nAtNumb = NULL;
     678                 :             :     }
     679                 :         175 : }
     680                 :             : 
     681                 :             : 
     682                 :             : /****************************************************************************/
     683                 :         525 : int NodeSetCreate( struct tagCANON_GLOBALS *pCG,
     684                 :             :                    NodeSet *pSet,
     685                 :             :                    int n,
     686                 :             :                    int L )
     687                 :             : {
     688                 :             :     int i, len;
     689                 :             : 
     690                 :         525 :     len = ( n + pCG->m_num_bit - 1 ) / pCG->m_num_bit;
     691                 :             : 
     692                 :         525 :     pSet->bitword = (bitWord**) inchi_calloc( L, sizeof( pSet->bitword[0] ) );
     693                 :             : 
     694         [ -  + ]:         525 :     if (!pSet->bitword)
     695                 :             :     {
     696                 :           0 :         return 0;
     697                 :             :     }
     698                 :         525 :     pSet->bitword[0] = (bitWord*) inchi_calloc( (long long)len * (long long)L, sizeof( pSet->bitword[0][0] ) ); /* djb-rwth: cast operators added */
     699         [ -  + ]:         525 :     if (!pSet->bitword[0])
     700                 :             :     {
     701                 :             :         /* Cleanup */
     702         [ #  # ]:           0 :         inchi_free( pSet->bitword );
     703                 :           0 :         pSet->bitword = NULL;
     704                 :           0 :         return 0; /* failed */
     705                 :             :     }
     706         [ +  + ]:      716975 :     for (i = 1; i < L; i++)
     707                 :             :     {
     708                 :      716450 :         pSet->bitword[i] = pSet->bitword[i - 1] + len;
     709                 :             :     }
     710                 :             : 
     711                 :         525 :     pSet->len_set = len;
     712                 :         525 :     pSet->num_set = L;
     713                 :             : 
     714                 :         525 :     return 1;
     715                 :             : }
     716                 :             : 
     717                 :             : 
     718                 :             : /****************************************************************************/
     719                 :         525 : void NodeSetFree( struct tagCANON_GLOBALS *pCG, NodeSet *pSet )
     720                 :             : {
     721   [ +  -  +  - ]:         525 :     if (pSet && pSet->bitword)
     722                 :             :     {
     723         [ +  - ]:         525 :         if (pSet->bitword[0])
     724                 :             :         {
     725         [ +  - ]:         525 :             inchi_free( pSet->bitword[0] );
     726                 :             :         }
     727         [ +  - ]:         525 :         inchi_free( pSet->bitword );
     728                 :         525 :         pSet->bitword = NULL;
     729                 :             :     }
     730                 :         525 : }
     731                 :             : 
     732                 :             : 
     733                 :             : /****************************************************************************/
     734                 :         686 : int CTableCreate( ConTable *Ct, int n, CANON_DATA *pCD )
     735                 :             : {
     736                 :         686 :     int maxlenCt = pCD->nMaxLenLinearCT + 1; /* add one element for CtPartINCHI_CANON_INFINITY() */
     737         [ +  + ]:         686 :     int maxlenNumH = pCD->NumH ? ( pCD->maxlenNumH + 1 ) : 0;
     738         [ -  + ]:         686 :     int maxlenNumHfixed = pCD->NumHfixed ? ( pCD->maxlenNumHfixed + 1 ) : 0;
     739         [ -  + ]:         686 :     int maxlenIso = pCD->maxlen_iso_sort_key ? ( pCD->maxlen_iso_sort_key + 1 ) : 0;
     740         [ -  + ]:         686 :     int maxlenIsoExchg = pCD->iso_exchg_atnos ? ( pCD->maxlen_iso_exchg_atnos + 1 ) : 0;
     741                 :             : 
     742                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
     743                 :             :     int maxlenIsoHfixed = pCD->maxlen_iso_sort_key_Hfixed ? ( pCD->maxlen_iso_sort_key_Hfixed + 1 ) : 0;
     744                 :             : #endif
     745                 :             : 
     746                 :         686 :     memset( Ct, 0, sizeof( Ct[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     747                 :             : 
     748                 :         686 :     Ct->maxVert = n;
     749                 :             : 
     750                 :         686 :     n++;
     751                 :             : 
     752                 :         686 :     Ct->Ctbl = (AT_RANK*) inchi_calloc( maxlenCt, sizeof( Ct->Ctbl[0] ) );
     753                 :         686 :     Ct->nextCtblPos = (AT_NUMB*) inchi_calloc( n, sizeof( Ct->nextCtblPos[0] ) );
     754                 :         686 :     Ct->nextAtRank = (AT_RANK*) inchi_calloc( n, sizeof( Ct->nextAtRank[0] ) );
     755         [ +  + ]:         686 :     if (maxlenNumH)
     756                 :             :     {
     757                 :         203 :         Ct->NumH = (NUM_H *) inchi_calloc( maxlenNumH, sizeof( Ct->NumH[0] ) );
     758                 :             :     }
     759         [ -  + ]:         686 :     if (maxlenNumHfixed)
     760                 :             :     {
     761                 :           0 :         Ct->NumHfixed = (NUM_H *) inchi_calloc( maxlenNumHfixed, sizeof( Ct->NumH[0] ) );
     762                 :             :     }
     763         [ -  + ]:         686 :     if (maxlenIso)
     764                 :             :     {
     765                 :           0 :         Ct->iso_sort_key = (AT_ISO_SORT_KEY *) inchi_calloc( maxlenIso, sizeof( Ct->iso_sort_key[0] ) );
     766                 :             :     }
     767         [ -  + ]:         686 :     if (maxlenIsoExchg)
     768                 :             :     {
     769                 :           0 :         Ct->iso_exchg_atnos = (S_CHAR *) inchi_calloc( maxlenIsoExchg, sizeof( Ct->iso_exchg_atnos[0] ) );
     770                 :             :     }
     771                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
     772                 :             :     if (maxlenIsoHfixed)
     773                 :             :     {
     774                 :             :         Ct->iso_sort_key_Hfixed = (AT_ISO_SORT_KEY *) inchi_calloc( maxlenIsoHfixed, sizeof( Ct->iso_sort_key_Hfixed[0] ) );
     775                 :             :     }
     776                 :             : #endif
     777                 :             : #ifdef INCHI_CANON_USE_HASH
     778                 :             :     Ct->hash = (CtHash*) inchi_calloc( n, sizeof( Ct->hash[0] ) );
     779                 :             : #endif
     780                 :             : 
     781                 :         686 :     Ct->lenCt = 0;
     782                 :         686 :     Ct->nLenCTAtOnly = pCD->nLenCTAtOnly;
     783                 :         686 :     Ct->maxlenCt = maxlenCt;
     784                 :         686 :     Ct->lenNumH = 0;
     785                 :         686 :     Ct->maxlenNumH = maxlenNumH;
     786                 :         686 :     Ct->len_iso_sort_key = 0;
     787                 :         686 :     Ct->maxlen_iso_sort_key = maxlenIso;
     788                 :         686 :     Ct->len_iso_exchg_atnos = 0;
     789                 :         686 :     Ct->maxlen_iso_exchg_atnos = maxlenIso;
     790                 :             : 
     791                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
     792                 :             :     Ct->len_iso_sort_key_Hfixed = 0;
     793                 :             :     Ct->maxlen_iso_sort_key_Hfixed = maxlenIsoHfixed;
     794                 :             : #endif
     795                 :             : 
     796                 :         686 :     Ct->maxPos = n;
     797                 :         686 :     Ct->lenPos = 0;
     798                 :             :     /* djb-rwth: fixing a NULL pointer dereferences */
     799         [ +  - ]:         686 :     if (Ct->nextAtRank)
     800                 :         686 :         Ct->nextAtRank[0] = 0;
     801         [ +  - ]:         686 :     if (Ct->nextCtblPos)
     802                 :         686 :         Ct->nextCtblPos[0] = 0;
     803                 :             : 
     804   [ +  -  +  -  :         686 :     if (Ct->Ctbl && Ct->nextCtblPos &&
                   +  + ]
     805   [ +  -  -  + ]:         686 :         ( !maxlenNumH || Ct->NumH ) &&
     806         [ #  # ]:           0 :         ( !maxlenNumHfixed || Ct->NumHfixed ))
     807                 :             :     {
     808                 :         686 :         return 1;
     809                 :             :     }
     810                 :             : 
     811                 :           0 :     return 0;
     812                 :             : }
     813                 :             : 
     814                 :             : 
     815                 :             : /****************************************************************************/
     816                 :         686 : void CTableFree( ConTable *Ct )
     817                 :             : {
     818         [ +  - ]:         686 :     if (Ct)
     819                 :             :     {
     820         [ +  + ]:         686 :         if (Ct->Ctbl)
     821                 :             :         {
     822         [ +  - ]:         525 :             inchi_free( Ct->Ctbl );
     823                 :             :         }
     824         [ +  - ]:         686 :         if (Ct->nextCtblPos)
     825                 :             :         {
     826         [ +  - ]:         686 :             inchi_free( Ct->nextCtblPos );
     827                 :             :         }
     828         [ +  - ]:         686 :         if (Ct->nextAtRank)
     829                 :             :         {
     830         [ +  - ]:         686 :             inchi_free( Ct->nextAtRank );
     831                 :             :         }
     832         [ +  + ]:         686 :         if (Ct->NumH)
     833                 :             :         {
     834         [ +  - ]:          42 :             inchi_free( Ct->NumH );
     835                 :             :         }
     836         [ -  + ]:         686 :         if (Ct->NumHfixed)
     837                 :             :         {
     838         [ #  # ]:           0 :             inchi_free( Ct->NumHfixed );
     839                 :             :         }
     840         [ -  + ]:         686 :         if (Ct->iso_sort_key)
     841                 :             :         {
     842         [ #  # ]:           0 :             inchi_free( Ct->iso_sort_key );
     843                 :             :         }
     844         [ -  + ]:         686 :         if (Ct->iso_exchg_atnos)
     845                 :             :         {
     846         [ #  # ]:           0 :             inchi_free( Ct->iso_exchg_atnos );
     847                 :             :         }
     848                 :             : 
     849                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
     850                 :             :         if (Ct->iso_sort_key_Hfixed)
     851                 :             :         {
     852                 :             :             inchi_free( Ct->iso_sort_key_Hfixed );
     853                 :             :         }
     854                 :             : #endif
     855                 :             : 
     856                 :             : #ifdef INCHI_CANON_USE_HASH
     857                 :             :         if (Ct->hash)
     858                 :             :         {
     859                 :             :             inchi_free( Ct->hash );
     860                 :             :         }
     861                 :             : #endif
     862                 :             : 
     863                 :         686 :         memset( Ct, 0, sizeof( Ct[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     864                 :             :     }
     865                 :         686 : }
     866                 :             : 
     867                 :             : 
     868                 :             : /****************************************************************************/
     869                 :         350 : int UnorderedPartitionCreate( UnorderedPartition *p, int n )
     870                 :             : {
     871                 :         350 :     p->equ2 = (AT_NUMB*) inchi_calloc( n, sizeof( p->equ2[0] ) );
     872                 :             :     /* p->next = (AT_NUMB*)inchi_calloc( n, sizeof(p->next[0])); */
     873                 :             : 
     874         [ +  - ]:         350 :     if (p->equ2 /*&& p->next*/)
     875                 :             :     {
     876                 :         350 :         return 1;
     877                 :             :     }
     878                 :             : 
     879                 :           0 :     return 0;
     880                 :             : }
     881                 :             : 
     882                 :             : 
     883                 :             : /****************************************************************************/
     884                 :         350 : void UnorderedPartitionFree( UnorderedPartition *p )
     885                 :             : {
     886         [ +  - ]:         350 :     if (p->equ2)
     887                 :             :     {
     888         [ +  - ]:         350 :         inchi_free( p->equ2 );
     889                 :             :     }
     890                 :             : 
     891                 :             :     /* if (p->next) inchi_free( p->next); */
     892                 :         350 :     p->equ2 = NULL;
     893                 :             :     /* p->next = NULL; */
     894                 :         350 : }
     895                 :             : 
     896                 :             : 
     897                 :             : /****************************************************************************/
     898                 :         175 : void UnorderedPartitionMakeDiscrete( UnorderedPartition *p, int n )
     899                 :             : {
     900                 :             :     int i;
     901         [ +  + ]:        1048 :     for (i = 0; i < n; i++)
     902                 :             :     {
     903                 :         873 :         p->equ2[i] = (AT_NUMB) i;
     904                 :             :         /* p->next[i] = INCHI_CANON_INFINITY; */
     905                 :             :     }
     906                 :             :     INCHI_HEAPCHK
     907                 :         175 : }
     908                 :             : 
     909                 :             : 
     910                 :             : /****************************************************************************/
     911                 :         350 : int PartitionCreate( Partition *p, int n )
     912                 :             : {
     913                 :         350 :     p->AtNumber = (AT_NUMB*) inchi_calloc( n, sizeof( p->AtNumber[0] ) );
     914                 :         350 :     p->Rank = (AT_RANK*) inchi_calloc( n, sizeof( p->Rank[0] ) );
     915   [ +  -  +  - ]:         350 :     if (p->AtNumber && p->Rank)
     916                 :             :     {
     917                 :         350 :         return 1;
     918                 :             :     }
     919                 :           0 :     return 0;
     920                 :             : }
     921                 :             : 
     922                 :             : 
     923                 :             : /****************************************************************************/
     924                 :         994 : void PartitionFree( Partition *p )
     925                 :             : {
     926         [ +  - ]:         994 :     if (p)
     927                 :             :     {
     928         [ +  + ]:         994 :         if (p->AtNumber)
     929                 :             :         {
     930         [ +  - ]:         511 :             inchi_free( p->AtNumber );
     931                 :         511 :             p->AtNumber = NULL;
     932                 :             :         }
     933         [ +  + ]:         994 :         if (p->Rank)
     934                 :             :         {
     935         [ +  - ]:         511 :             inchi_free( p->Rank );
     936                 :         511 :             p->Rank = NULL;
     937                 :             :         }
     938                 :             :     }
     939                 :         994 : }
     940                 :             : 
     941                 :             : 
     942                 :             : /****************************************************************************/
     943                 :         394 : int PartitionIsDiscrete( Partition *p, int n )
     944                 :             : {
     945                 :             :     int i;
     946                 :             :     AT_RANK r;
     947         [ +  + ]:        2295 :     for (i = 0, r = 1; i < n; i++, r++)
     948                 :             :     {
     949         [ +  + ]:        2047 :         if (r != ( rank_mask_bit & p->Rank[p->AtNumber[i]] ))
     950                 :             :         {
     951                 :             :             INCHI_HEAPCHK
     952                 :         146 :             return 0;
     953                 :             :         }
     954                 :             :     }
     955                 :             : 
     956                 :             :     INCHI_HEAPCHK
     957                 :             : 
     958                 :         248 :     return 1;
     959                 :             : }
     960                 :             : 
     961                 :             : 
     962                 :             : /****************************************************************************/
     963                 :         146 : int PartitionGetFirstCell( Partition *p, Cell *baseW, int k, int n )
     964                 :             : {
     965                 :             :     int i;
     966                 :             :     AT_RANK r;
     967                 :         146 :     Cell *W = baseW + k - 1;
     968                 :             : 
     969         [ +  + ]:         146 :     i = ( k > 1 ) ? baseW[k - 2].first + 1 : 0;
     970                 :             : 
     971         [ +  - ]:         146 :     if (i < n)
     972                 :             :     {
     973                 :             :         /* bypass single vertex cells */
     974   [ +  -  +  + ]:         233 :         for (r = (AT_RANK) ( i + 1 ); i < n && r == ( rank_mask_bit & p->Rank[(int) p->AtNumber[i]] ); i++, r++)
     975                 :             :         {
     976                 :             :             ;
     977                 :             :         }
     978                 :             :     }
     979         [ +  - ]:         146 :     if (i < n)
     980                 :             :     {
     981                 :         146 :         W->first = i;
     982                 :         146 :         for (r = ( rank_mask_bit & p->Rank[(int) p->AtNumber[i]] ), i++;
     983   [ +  +  +  + ]:         332 :               i < n && r == ( rank_mask_bit & p->Rank[(int) p->AtNumber[i]] );
     984                 :         186 :               i++)
     985                 :             :         {
     986                 :             :             ;
     987                 :             :         }
     988                 :         146 :         W->next = i;
     989                 :             : 
     990                 :             :         INCHI_HEAPCHK
     991                 :             : 
     992                 :         146 :         return ( W->next - W->first );
     993                 :             :     }
     994                 :             : 
     995                 :           0 :     W->first = INCHI_CANON_INFINITY;
     996                 :           0 :     W->next = 0;
     997                 :             : 
     998                 :             :     INCHI_HEAPCHK
     999                 :             : 
    1000                 :           0 :     return 0;
    1001                 :             : }
    1002                 :             : 
    1003                 :             : 
    1004                 :             : /****************************************************************************/
    1005                 :         179 : void CellMakeEmpty( Cell *baseW, int k )
    1006                 :             : {
    1007                 :         179 :     k--;
    1008                 :         179 :     baseW[k].first = INCHI_CANON_INFINITY;
    1009                 :         179 :     baseW[k].next = 0;
    1010                 :         179 :     baseW[k].prev = -1;
    1011                 :             : 
    1012                 :             :     INCHI_HEAPCHK
    1013                 :         179 : }
    1014                 :             : 
    1015                 :             : 
    1016                 :             : /****************************************************************************/
    1017                 :           0 : void NodeSetFromVertices( CANON_GLOBALS *pCG, NodeSet *cur_nodes, int l, Node *v, int num_v )
    1018                 :             : {
    1019                 :           0 :     bitWord *Bits = cur_nodes->bitword[l - 1];
    1020                 :           0 :     int      len = cur_nodes->len_set * sizeof( bitWord );
    1021                 :             :     int      i, j;
    1022                 :             : 
    1023                 :           0 :     memset( Bits, 0, len ); /* djb-rwth: memset_s C11/Annex K variant? */
    1024                 :             : 
    1025         [ #  # ]:           0 :     for (i = 0; i < num_v; i++)
    1026                 :             :     {
    1027                 :           0 :         j = (int) v[i] - 1;
    1028                 :           0 :         Bits[j / pCG->m_num_bit] |= pCG->m_bBit[j % pCG->m_num_bit];
    1029                 :             :     }
    1030                 :             : 
    1031                 :             :     INCHI_HEAPCHK
    1032                 :           0 : }
    1033                 :             : 
    1034                 :             : 
    1035                 :             : /****************************************************************************/
    1036                 :           0 : int AllNodesAreInSet( NodeSet *cur_nodes, int lcur_nodes, NodeSet *set, int lset )
    1037                 :             : {
    1038                 :             :     int i;
    1039                 :           0 :     int n = cur_nodes->len_set;
    1040                 :             : 
    1041                 :           0 :     bitWord *BitsNode = cur_nodes->bitword[lcur_nodes - 1];
    1042                 :           0 :     bitWord *BitsSet = set->bitword[lset - 1];
    1043                 :             : 
    1044                 :             :     /* find any BitsNode[i] bit not in BitsSet[i] */
    1045         [ #  # ]:           0 :     for (i = 0; i < n; i++)
    1046                 :             :     {
    1047         [ #  # ]:           0 :         if (BitsNode[i] & ~BitsSet[i])
    1048                 :             :         {
    1049                 :             : 
    1050                 :             :             INCHI_HEAPCHK
    1051                 :             : 
    1052                 :           0 :                 return 0;
    1053                 :             :         }
    1054                 :             :     }
    1055                 :             : 
    1056                 :             :     INCHI_HEAPCHK
    1057                 :             : 
    1058                 :           0 :     return 1;
    1059                 :             : }
    1060                 :             : 
    1061                 :             : 
    1062                 :             : /****************************************************************************/
    1063                 :           0 : void PartitionGetMcrAndFixSet( CANON_GLOBALS *pCG,
    1064                 :             :                                Partition *p,
    1065                 :             :                                NodeSet *Mcr,
    1066                 :             :                                NodeSet *Fix,
    1067                 :             :                                int n,
    1068                 :             :                                int l )
    1069                 :             : {
    1070                 :             :     int i, j1, j2;
    1071                 :             :     AT_RANK r, r1;
    1072                 :           0 :     bitWord *McrBits = Mcr->bitword[l - 1];
    1073                 :           0 :     bitWord *FixBits = Fix->bitword[l - 1];
    1074                 :           0 :     int     len = Mcr->len_set * sizeof( bitWord );
    1075                 :             : 
    1076                 :           0 :     memset( McrBits, 0, len ); /* djb-rwth: memset_s C11/Annex K variant? */
    1077                 :           0 :     memset( FixBits, 0, len ); /* djb-rwth: memset_s C11/Annex K variant? */
    1078         [ #  # ]:           0 :     for (i = 0, r = 1; i < n; i++, r++)
    1079                 :             :     {
    1080         [ #  # ]:           0 :         if (r == ( r1 = ( rank_mask_bit&p->Rank[j1 = (int) p->AtNumber[i]] ) ))
    1081                 :             :         {
    1082                 :           0 :             FixBits[j1 / pCG->m_num_bit] |= pCG->m_bBit[j1 % pCG->m_num_bit];
    1083                 :           0 :             McrBits[j1 / pCG->m_num_bit] |= pCG->m_bBit[j1 % pCG->m_num_bit];
    1084                 :             :         }
    1085                 :             :         else
    1086                 :             :         {
    1087   [ #  #  #  # ]:           0 :             for (r = r1; i + 1 < n && r == ( rank_mask_bit&p->Rank[j2 = (int) p->AtNumber[i + 1]] ); i++)
    1088                 :             :             {
    1089         [ #  # ]:           0 :                 if (j1 > j2)
    1090                 :             :                 {
    1091                 :           0 :                     j1 = j2;
    1092                 :             :                 }
    1093                 :             :             }
    1094                 :           0 :             McrBits[j1 / pCG->m_num_bit] |= pCG->m_bBit[j1 % pCG->m_num_bit];
    1095                 :             :         }
    1096                 :             :     }
    1097                 :             : 
    1098                 :             :     INCHI_HEAPCHK
    1099                 :           0 : }
    1100                 :             : 
    1101                 :             : 
    1102                 :             : /************* used in ichi_bns.c ********************************/
    1103                 :           0 : void NodeSetFromRadEndpoints( CANON_GLOBALS *pCG,
    1104                 :             :                               NodeSet *cur_nodes,
    1105                 :             :                               int k, /*Node *v*/
    1106                 :             :                               Vertex RadEndpoints[],
    1107                 :             :                               int num_v )
    1108                 :             : {
    1109                 :           0 :     bitWord *Bits = cur_nodes->bitword[k];
    1110                 :           0 :     int      len = cur_nodes->len_set * sizeof( bitWord );
    1111                 :             :     int      i, j;
    1112                 :             : 
    1113                 :           0 :     memset( Bits, 0, len ); /* djb-rwth: memset_s C11/Annex K variant? */
    1114                 :             : 
    1115         [ #  # ]:           0 :     for (i = 1; i < num_v; i += 2)
    1116                 :             :     {
    1117                 :           0 :         j = (int) RadEndpoints[i];
    1118                 :           0 :         Bits[j / pCG->m_num_bit] |= pCG->m_bBit[j % pCG->m_num_bit];
    1119                 :             :     }
    1120                 :           0 : }
    1121                 :             : 
    1122                 :             : 
    1123                 :             : /************* used in ichi_bns.c ********************************/
    1124                 :           0 : void RemoveFromNodeSet( CANON_GLOBALS *pCG,
    1125                 :             :                         NodeSet *cur_nodes, int k, Vertex v[], int num_v )
    1126                 :             : {
    1127         [ #  # ]:           0 :     if (cur_nodes->bitword)
    1128                 :             :     {
    1129                 :           0 :         bitWord *Bits = cur_nodes->bitword[k];
    1130                 :             :         /*int      len  = cur_nodes->len_set*sizeof(bitWord);*/
    1131                 :             :         int      i, j;
    1132                 :             : 
    1133         [ #  # ]:           0 :         for (i = 0; i < num_v; i++)
    1134                 :             :         {
    1135                 :           0 :             j = (int) v[i];
    1136                 :           0 :             Bits[j / pCG->m_num_bit] &= ~pCG->m_bBit[j % pCG->m_num_bit];
    1137                 :             :         }
    1138                 :             :     }
    1139                 :           0 : }
    1140                 :             : 
    1141                 :             : 
    1142                 :             : /************* used in ichi_bns.c ********************************/
    1143                 :           0 : int DoNodeSetsIntersect( NodeSet *cur_nodes, int k1, int k2 )
    1144                 :             : {
    1145         [ #  # ]:           0 :     if (cur_nodes->bitword)
    1146                 :             :     {
    1147                 :           0 :         bitWord *Bits1 = cur_nodes->bitword[k1];
    1148                 :           0 :         bitWord *Bits2 = cur_nodes->bitword[k2];
    1149                 :           0 :         int      len = cur_nodes->len_set;
    1150                 :             :         int      i;
    1151                 :             : 
    1152         [ #  # ]:           0 :         for (i = 0; i < len; i++)
    1153                 :             :         {
    1154         [ #  # ]:           0 :             if (Bits1[i] & Bits2[i])
    1155                 :             :             {
    1156                 :           0 :                 return 1;
    1157                 :             :             }
    1158                 :             :         }
    1159                 :             :     }
    1160                 :             : 
    1161                 :           0 :     return 0;
    1162                 :             : }
    1163                 :             : 
    1164                 :             : 
    1165                 :             : /************* used in ichi_bns.c ********************************/
    1166                 :           0 : int IsNodeSetEmpty( NodeSet *cur_nodes, int k )
    1167                 :             : {
    1168         [ #  # ]:           0 :     if (cur_nodes->bitword)
    1169                 :             :     {
    1170                 :           0 :         bitWord *Bits = cur_nodes->bitword[k];
    1171                 :           0 :         int      len = cur_nodes->len_set;
    1172                 :             :         int      i;
    1173                 :             : 
    1174         [ #  # ]:           0 :         for (i = 0; i < len; i++)
    1175                 :             :         {
    1176         [ #  # ]:           0 :             if (Bits[i])
    1177                 :             :             {
    1178                 :           0 :                 return 0;
    1179                 :             :             }
    1180                 :             :         }
    1181                 :             :     }
    1182                 :             : 
    1183                 :           0 :     return 1;
    1184                 :             : }
    1185                 :             : 
    1186                 :             : 
    1187                 :             : /************* used in ichi_bns.c ********************************/
    1188                 :           0 : void AddNodeSet2ToNodeSet1( NodeSet *cur_nodes, int k1, int k2 )
    1189                 :             : {
    1190         [ #  # ]:           0 :     if (cur_nodes->bitword)
    1191                 :             :     {
    1192                 :           0 :         bitWord *Bits1 = cur_nodes->bitword[k1];
    1193                 :           0 :         bitWord *Bits2 = cur_nodes->bitword[k2];
    1194                 :           0 :         int      len = cur_nodes->len_set;
    1195                 :             :         int      i;
    1196                 :             : 
    1197         [ #  # ]:           0 :         for (i = 0; i < len; i++)
    1198                 :             :         {
    1199                 :           0 :             Bits1[i] |= Bits2[i];
    1200                 :             :         }
    1201                 :             :     }
    1202                 :           0 : }
    1203                 :             : 
    1204                 :             : 
    1205                 :             : /************* used in ichi_bns.c ********************************/
    1206                 :           0 : int AddNodesToRadEndpoints( CANON_GLOBALS *pCG,
    1207                 :             :                             NodeSet *cur_nodes,
    1208                 :             :                             int k,
    1209                 :             :                             Vertex RadEndpoints[],
    1210                 :             :                             Vertex vRad,
    1211                 :             :                             int nStart, int nLen )
    1212                 :             : {
    1213                 :           0 :     int n = nStart;
    1214         [ #  # ]:           0 :     if (cur_nodes->bitword)
    1215                 :             :     {
    1216                 :           0 :         bitWord *Bits = cur_nodes->bitword[k];
    1217                 :           0 :         int      len = cur_nodes->len_set;
    1218                 :             :         int      i, j;
    1219                 :             :         Vertex   v;
    1220                 :             : 
    1221         [ #  # ]:           0 :         for (i = 0, v = 0; i < len; i++)
    1222                 :             :         {
    1223         [ #  # ]:           0 :             if (Bits[i])
    1224                 :             :             {
    1225         [ #  # ]:           0 :                 for (j = 0; j < pCG->m_num_bit; j++, v++)
    1226                 :             :                 {
    1227         [ #  # ]:           0 :                     if (Bits[i] & pCG->m_bBit[j])
    1228                 :             :                     {
    1229         [ #  # ]:           0 :                         if (n >= nLen)
    1230                 :             :                         {
    1231                 :           0 :                             return -1; /* overflow */
    1232                 :             :                         }
    1233                 :           0 :                         RadEndpoints[n++] = vRad;
    1234                 :           0 :                         RadEndpoints[n++] = v;
    1235                 :             :                     }
    1236                 :             :                 }
    1237                 :             :             }
    1238                 :             :             else
    1239                 :             :             {
    1240                 :           0 :                 v += pCG->m_num_bit;
    1241                 :             :             }
    1242                 :             :         }
    1243                 :             :     }
    1244                 :             : 
    1245                 :           0 :     return n;
    1246                 :             : }
    1247                 :             : 
    1248                 :             : 
    1249                 :             : /****************************************************************************/
    1250                 :          73 : void PartitionGetTransposition( Partition *pFrom,
    1251                 :             :                                 Partition *pTo,
    1252                 :             :                                 int n,
    1253                 :             :                                 Transposition *gamma )
    1254                 :             : {
    1255                 :             :     int i;
    1256                 :             : 
    1257         [ +  + ]:         701 :     for (i = 0; i < n; i++)
    1258                 :             :     {
    1259                 :         628 :         gamma->nAtNumb[(int) pFrom->AtNumber[i]] = pTo->AtNumber[i];
    1260                 :             :     }
    1261                 :             : 
    1262                 :             :     INCHI_HEAPCHK
    1263                 :          73 : }
    1264                 :             : 
    1265                 :             : 
    1266                 :             : /****************************************************************************
    1267                 :             :   Get minimal set (class) representative and partially compress the
    1268                 :             :   partitioning mcr = minimal class representative.
    1269                 :             : ****************************************************************************/
    1270                 :        2557 : AT_RANK nGetMcr2( AT_RANK *nEqArray, AT_RANK n )
    1271                 :             : {
    1272                 :             :     AT_RANK n1, n2, mcr; /*  recursive version is much shorter. */
    1273                 :             : 
    1274                 :             :     INCHI_HEAPCHK
    1275                 :             : 
    1276                 :        2557 :     n1 = nEqArray[(int) n];
    1277                 :             : 
    1278         [ +  + ]:        2557 :     if (n == n1)
    1279                 :             :     {
    1280                 :        2134 :         return n;
    1281                 :             :     }
    1282                 :             : 
    1283                 :             :     /*  1st pass: find mcr */
    1284         [ +  + ]:         466 :     while (n1 != ( n2 = nEqArray[(int) n1] ))
    1285                 :             :     {
    1286                 :          43 :         n1 = n2;
    1287                 :             :     }
    1288                 :             : 
    1289                 :             :     /*  2nd pass: copy mcr to each element of the set starting from nEqArray[n] */
    1290                 :         423 :     mcr = n1;
    1291                 :         423 :     n1 = n;
    1292         [ +  + ]:         466 :     while ( /*n1*/ mcr != ( n2 = nEqArray[(int) n1] ))
    1293                 :             :     {
    1294                 :          43 :         nEqArray[(int) n1] = mcr;
    1295                 :          43 :         n1 = n2;
    1296                 :             :     }
    1297                 :             : 
    1298                 :             :     INCHI_HEAPCHK
    1299                 :             : 
    1300                 :         423 :     return ( mcr );
    1301                 :             : }
    1302                 :             : 
    1303                 :             : 
    1304                 :             : /****************************************************************************
    1305                 :             :   Join 2 sets (classes) that have members n1 and n2
    1306                 :             : ****************************************************************************/
    1307                 :         141 : int nJoin2Mcrs2( AT_RANK *nEqArray, AT_RANK n1, AT_RANK n2 )
    1308                 :             : {
    1309                 :         141 :     n1 = nGetMcr2( nEqArray, n1 );
    1310                 :         141 :     n2 = nGetMcr2( nEqArray, n2 );
    1311                 :             : 
    1312         [ +  + ]:         141 :     if (n1 < n2)
    1313                 :             :     {
    1314                 :           2 :         nEqArray[n2] = n1;
    1315                 :             : 
    1316                 :             :         INCHI_HEAPCHK
    1317                 :             : 
    1318                 :           2 :         return 1; /*  a change has been made */
    1319                 :             :     }
    1320                 :             : 
    1321         [ +  + ]:         139 :     if (n2 < n1)
    1322                 :             :     {
    1323                 :         128 :         nEqArray[n1] = n2;
    1324                 :             : 
    1325                 :             :         INCHI_HEAPCHK
    1326                 :             : 
    1327                 :         128 :         return 1; /*  a change has been made */
    1328                 :             :     }
    1329                 :             : 
    1330                 :             :     INCHI_HEAPCHK
    1331                 :             : 
    1332                 :          11 :     return 0; /*  no changes */
    1333                 :             : }
    1334                 :             : 
    1335                 :             : 
    1336                 :             : /****************************************************************************/
    1337                 :        2275 : Node GetUnorderedPartitionMcrNode( UnorderedPartition *p1, Node v )
    1338                 :             : {
    1339                 :        2275 :     Node ret = (Node) ( 1 + nGetMcr2( p1->equ2, (AT_RANK) ( v - 1 ) ) );
    1340                 :             : 
    1341                 :             :     INCHI_HEAPCHK
    1342                 :             : 
    1343                 :        2275 :     return ret;
    1344                 :             : }
    1345                 :             : 
    1346                 :             : 
    1347                 :             : /****************************************************************************
    1348                 :             :  Change p2 to (p2 v p1)
    1349                 :             : ****************************************************************************/
    1350                 :          73 : int UnorderedPartitionJoin( UnorderedPartition *p1,
    1351                 :             :                             UnorderedPartition *p2,
    1352                 :             :                             int n )
    1353                 :             : {
    1354                 :             :     int i, j;
    1355                 :          73 :     int nNumChanges = 0;
    1356         [ +  + ]:         701 :     for (i = 0; i < n; i++)
    1357                 :             :     {
    1358   [ +  +  -  + ]:         628 :         if (( j = (int) p1->equ2[i] ) == i || p2->equ2[(int) i] == p2->equ2[(int) j])
    1359                 :             :         {
    1360                 :         487 :             continue;
    1361                 :             :         }
    1362                 :         141 :         nNumChanges += nJoin2Mcrs2( p2->equ2, (AT_NUMB) i, (AT_NUMB) j );
    1363                 :             :     }
    1364                 :             : 
    1365                 :             :     INCHI_HEAPCHK
    1366                 :             : 
    1367                 :          73 :     return nNumChanges;
    1368                 :             : }
    1369                 :             : 
    1370                 :             : 
    1371                 :             : /****************************************************************************/
    1372                 :         121 : int PartitionSatisfiesLemma_2_25( Partition *p, int n )
    1373                 :             : {
    1374                 :         121 :     int nPartitionSize = 0;
    1375                 :         121 :     int nNumNonTrivialCells = 0;
    1376                 :             :     AT_RANK r;
    1377                 :             :     int i, num;
    1378                 :             : 
    1379         [ +  + ]:        1128 :     for (i = num = 0, r = 1; i < n; i++, r++)
    1380                 :             :     {
    1381         [ +  + ]:        1007 :         if (( rank_mask_bit & p->Rank[(int) p->AtNumber[i]] ) == r)
    1382                 :             :         {
    1383                 :         680 :             nPartitionSize++;
    1384         [ +  + ]:         680 :             if (num)
    1385                 :             :             {
    1386                 :             :                 /* num+1 = cell size > 1 */
    1387                 :         245 :                 nNumNonTrivialCells++;
    1388                 :         245 :                 num = 0;
    1389                 :             :             }
    1390                 :             :         }
    1391                 :             :         else
    1392                 :             :         {
    1393                 :         327 :             num++;
    1394                 :             :         }
    1395                 :             :     }
    1396                 :             : 
    1397                 :             :     /* check Lemma_2_25 conditions */
    1398         [ +  + ]:         121 :     if (n <= nPartitionSize + 4 ||
    1399         [ +  + ]:          14 :          n == nPartitionSize + nNumNonTrivialCells ||
    1400         [ -  + ]:          10 :          n == nPartitionSize + nNumNonTrivialCells + 1)
    1401                 :             :     {
    1402                 :         111 :         return 1;
    1403                 :             :     }
    1404                 :             : 
    1405                 :          10 :     return 0;
    1406                 :             : }
    1407                 :             : 
    1408                 :             : 
    1409                 :             : /****************************************************************************/
    1410                 :         426 : void PartitionCopy( Partition *To, Partition *From, int n )
    1411                 :             : {
    1412                 :             :     int i;
    1413                 :         426 :     memcpy(To->AtNumber, From->AtNumber, n * sizeof(To->AtNumber[0]));
    1414                 :         426 :     memcpy(To->Rank, From->Rank, n * sizeof(To->AtNumber[0]));
    1415                 :             : 
    1416         [ +  + ]:        3510 :     for (i = 0; i < n; i++)
    1417                 :             :     {
    1418                 :        3084 :         To->Rank[i] &= rank_mask_bit;
    1419                 :             :     }
    1420                 :             : 
    1421                 :             :     INCHI_HEAPCHK
    1422                 :         426 : }
    1423                 :             : 
    1424                 :             : 
    1425                 :             : /****************************************************************************
    1426                 :             :  Makes new equitable partition (p+1) out of p;
    1427                 :             :  first reduce the rank of vertex v
    1428                 :             :  ***************************************************************************/
    1429                 :         219 : int PartitionColorVertex( CANON_GLOBALS *pCG,
    1430                 :             :                           Graph *G,
    1431                 :             :                           Partition *p,
    1432                 :             :                           Node v,
    1433                 :             :                           int n,
    1434                 :             :                           int n_tg,
    1435                 :             :                           int n_max,
    1436                 :             :                           int bDigraph,
    1437                 :             :                           int nNumPrevRanks )
    1438                 :             : {
    1439                 :             :     int     nNumNewRanks, i, j;
    1440                 :         219 :     long    lNumNeighListIter = 0;
    1441                 :             :     AT_RANK rv, r;
    1442                 :             :     AT_NUMB s, sv;
    1443                 :             : 
    1444         [ +  + ]:         657 :     for (i = 1; i <= 2; i++)
    1445                 :             :     {
    1446         [ +  + ]:         438 :         if (!p[i].AtNumber)
    1447                 :             :         {
    1448                 :          76 :             p[i].AtNumber = (AT_NUMB *) inchi_malloc( n_max * sizeof( p[0].AtNumber[0] ) );
    1449                 :             :         }
    1450         [ +  + ]:         438 :         if (!p[i].Rank)
    1451                 :             :         {
    1452                 :          76 :             p[i].Rank = (AT_RANK *) inchi_malloc( n_max * sizeof( p[0].Rank[0] ) );
    1453                 :             :         }
    1454   [ +  -  -  + ]:         438 :         if (!p[i].AtNumber || !p[i].Rank)
    1455                 :             :         {
    1456                 :             : 
    1457                 :             :             INCHI_HEAPCHK
    1458                 :             : 
    1459                 :           0 :             return CT_OUT_OF_RAM;
    1460                 :             :         }
    1461                 :             :     }
    1462                 :             : 
    1463                 :         219 :     PartitionCopy( p + 1, p, n_tg );
    1464                 :             : 
    1465                 :         219 :     sv = v - 1;          /* atom number we are looking for */
    1466         [ -  + ]:         219 :     if (sv >= (AT_NUMB) n_tg)
    1467                 :             :     {
    1468                 :             : 
    1469                 :             :         INCHI_HEAPCHK
    1470                 :             : 
    1471                 :           0 :         return CT_CANON_ERR; /* !!! severe program error: sv not found !!! */
    1472                 :             :     }
    1473                 :             : 
    1474                 :         219 :     rv = p[1].Rank[(int) sv];  /* rank of this atom */
    1475                 :             : 
    1476                 :             :     /* second, locate sv among all vertices that have same rank as v */
    1477                 :         219 :     s = n_max + 1; /* always greater than sv; this initialization is needed only to keep the compiler happy */
    1478   [ +  -  +  -  :         438 :     for (j = (int) rv - 1; 0 <= j && rv == ( p[1].Rank[(int) ( s = p[1].AtNumber[j] )] ) && s != sv; j--) /* djb-rwth: removing redundant code */
                   +  + ]
    1479                 :             :     {
    1480                 :             :         ;
    1481                 :             :     }
    1482                 :             : 
    1483         [ -  + ]:         219 :     if (s != sv)
    1484                 :             :     {
    1485                 :             :         INCHI_HEAPCHK
    1486                 :           0 :         return CT_CANON_ERR; /* !!! severe program error: sv not found !!! */
    1487                 :             :     }
    1488                 :             : 
    1489                 :             :     /* shift preceding atom numbers to the right to fill the gap after removing sv */
    1490                 :         219 :     r = rv - 1; /* initialization only to keep compiler happy */
    1491   [ +  +  +  + ]:         293 :     for (i = j--; 0 <= j && rv == ( r = p[1].Rank[(int) ( s = p[1].AtNumber[j] )] ); i = j, j--)
    1492                 :             :     {
    1493                 :          74 :         p[1].AtNumber[i] = s;
    1494                 :             :     }
    1495                 :             : 
    1496         [ +  + ]:         219 :     r = ( i > 0 ) ? ( r + 1 ) : 1;  /* new reduced rank = (next lower rank)+1 or 1 */
    1497                 :             :     /* insert sv and adjust its rank */
    1498                 :         219 :     p[1].AtNumber[i] = sv;
    1499                 :         219 :     p[1].Rank[(int) sv] = r;
    1500                 :             : 
    1501                 :             : 
    1502                 :             :     /* make equitable partition */
    1503         [ +  + ]:         219 :     if (bDigraph)
    1504                 :             :     {
    1505                 :             :         /*
    1506                 :             :         nNumNewRanks = DifferentiateRanks2( pCG, n_tg, G,
    1507                 :             :                                          nNumPrevRanks+1, p[1].Rank, p[2].Rank,
    1508                 :             :                                          p[1].AtNumber, &lNumNeighListIter, 1 );
    1509                 :             :         */
    1510                 :          71 :         nNumNewRanks = DifferentiateRanks4( pCG, n_tg, G,
    1511                 :          71 :                                          nNumPrevRanks + 1, p[1].Rank, p[2].Rank /* temp array */,
    1512                 :          71 :                                          p[1].AtNumber, (AT_RANK) n, &lNumNeighListIter );
    1513                 :             :     }
    1514                 :             :     else
    1515                 :             :     {
    1516                 :             :          /*
    1517                 :             :          nNumNewRanks = DifferentiateRanks2( pCG, n_tg, G,
    1518                 :             :                                           nNumPrevRanks+1, p[1].Rank, p[2].Rank,
    1519                 :             :                                           p[1].AtNumber, &lNumNeighListIter, 1 );
    1520                 :             :          */
    1521                 :         148 :         nNumNewRanks = DifferentiateRanks3( pCG, n_tg, G,
    1522                 :         148 :                                          nNumPrevRanks + 1, p[1].Rank, p[2].Rank /* temp array */,
    1523                 :         148 :                                          p[1].AtNumber, &lNumNeighListIter );
    1524                 :             :     }
    1525                 :             :     INCHI_HEAPCHK
    1526                 :             : 
    1527                 :         219 :     return nNumNewRanks;
    1528                 :             : }
    1529                 :             : 
    1530                 :             : 
    1531                 :             : /****************************************************************************/
    1532                 :             : typedef struct tagNodeValues
    1533                 :             : {
    1534                 :             :     NUM_H            NumH;
    1535                 :             :     AT_ISO_SORT_KEY  iso_sort_key;
    1536                 :             :     NUM_H            NumHfixed;
    1537                 :             : 
    1538                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    1539                 :             :     AT_ISO_SORT_KEY  iso_sort_key_Hfixed;
    1540                 :             : #endif
    1541                 :             : 
    1542                 :             :     AT_NUMB          nAtNumber;
    1543                 :             : } NV;
    1544                 :             : 
    1545                 :             : 
    1546                 :             : 
    1547                 :             : /****************************************************************************
    1548                 :             :  Return min node > vPrev or INCHI_CANON_INFINITY if not found
    1549                 :             :  Input: v = previous atom number + 1 or 0 on first call
    1550                 :             : ****************************************************************************/
    1551                 :         394 : Node CellGetMinNode( Partition *p, Cell *W, Node v, CANON_DATA *pCD )
    1552                 :             : {
    1553                 :             :     AT_NUMB i;
    1554                 :         394 :     AT_NUMB uCurAtNumb, uMinAtNumb = INCHI_CANON_INFINITY;
    1555                 :             : 
    1556                 :             :     /* in case of emty cell:  (W->first=INCHI_CANON_INFINITY) > (W->next=0); returns INCHI_CANON_INFINITY */
    1557         [ -  + ]:         394 :     if (W->first > W->next)
    1558                 :             :     {
    1559                 :           0 :         return INCHI_CANON_INFINITY;
    1560                 :             :     }
    1561                 :             : 
    1562                 :             : #if ( USE_AUX_RANKING == 1 )
    1563   [ +  -  +  + ]:         394 :     if (pCD && pCD->nAuxRank)
    1564                 :         121 :     {
    1565                 :             :         AT_RANK uMinAuxRank, uCurAuxRank;
    1566                 :             :         int     nCurAtNumb;
    1567                 :             : 
    1568                 :             : #if ( USE_AUX_RANKING_ALL == 1 )
    1569                 :             :         AT_RANK uInpAuxRank;
    1570                 :             :         int     nInpAtNumb, nMinAtNumb;
    1571                 :             : #endif
    1572                 :             : 
    1573         [ +  - ]:         121 :         for (i = W->first; i < W->next; i++)
    1574                 :             :         {
    1575                 :         121 :             uCurAtNumb = p->AtNumber[(int) i];
    1576         [ +  - ]:         121 :             if (!( p->Rank[(int) uCurAtNumb] & rank_mark_bit ))
    1577                 :             :             {
    1578                 :         121 :                 break; /* found the first unmarked yet node */
    1579                 :             :             }
    1580                 :             :         }
    1581         [ -  + ]:         121 :         if (i == W->next)
    1582                 :             :         {
    1583                 :           0 :             return INCHI_CANON_INFINITY;
    1584                 :             :         }
    1585                 :             : 
    1586                 :             : #if ( USE_AUX_RANKING_ALL == 1 )
    1587                 :             :         /*==== vertex ordering definition ===
    1588                 :             :          * vertex v1 < v2 <=> (AuxRank(v1)==AuxRank(v2) && AtNumb(v1) < AtNumb(v2)) || (AuxRank(v1) < AuxRank(v2))
    1589                 :             :          * vertex v1 > v2 <=> (AuxRank(v1)==AuxRank(v2) && AtNumb(v1) > AtNumb(v2)) || (AuxRank(v1) > AuxRank(v2))
    1590                 :             :          * vertex v1 = v2 <=> (AuxRank(v1)==AuxRank(v2) && AtNumb(v1) == AtNumb(v2))
    1591                 :             :          */
    1592                 :             : 
    1593                 :             :         /* set initial vMin so that vMin > any vertex */
    1594                 :         121 :         uMinAuxRank = INCHI_CANON_INFINITY;
    1595                 :         121 :         nMinAtNumb = INCHI_CANON_INFINITY;
    1596                 :             :         /* set vInp */
    1597         [ +  + ]:         121 :         if (v)
    1598                 :             :         {
    1599                 :          50 :             nInpAtNumb = (int) v - 1; /* previous vertex */
    1600                 :          50 :             uInpAuxRank = pCD->nAuxRank[nInpAtNumb];
    1601                 :             :         }
    1602                 :             :         else
    1603                 :             :         {
    1604                 :          71 :             nInpAtNumb = -1; /* less than any vertex */
    1605                 :          71 :             uInpAuxRank = 0;
    1606                 :             :         }
    1607                 :             :         /* find vMin = min { vCur : (vCur > vInp) && (vCur in W) } */
    1608         [ +  + ]:         409 :         for (; i < W->next; i++)
    1609                 :             :         {
    1610                 :         288 :             nCurAtNumb = (int) p->AtNumber[(int) i];
    1611         [ +  - ]:         288 :             if (!( p->Rank[nCurAtNumb] & rank_mark_bit ))
    1612                 :             :             {
    1613                 :             :                 /* vertex nCurAtNumb is not marked, find whether it fits the conditions */
    1614                 :         288 :                 uCurAuxRank = pCD->nAuxRank[nCurAtNumb];
    1615   [ +  +  +  +  :         288 :                 if ((uCurAuxRank == uInpAuxRank && nCurAtNumb > nInpAtNumb) || uCurAuxRank > uInpAuxRank) /* djb-rwth: addressing LLVM warning */
                   +  + ]
    1616                 :             :                 {
    1617                 :             :                     /* here vCur > vInp */
    1618   [ +  +  -  + ]:         199 :                     if (uCurAuxRank == uMinAuxRank && nCurAtNumb < nMinAtNumb)
    1619                 :             :                     {
    1620                 :             :                         /* vCur < vMin (1) */
    1621                 :           0 :                         nMinAtNumb = nCurAtNumb;
    1622                 :             :                     }
    1623         [ +  + ]:         199 :                     else if (uCurAuxRank < uMinAuxRank)
    1624                 :             :                     {
    1625                 :             :                         /* vCur < vMin (2) */
    1626                 :         100 :                         uMinAuxRank = uCurAuxRank;
    1627                 :         100 :                         nMinAtNumb = nCurAtNumb;
    1628                 :             :                     }
    1629                 :             :                 }
    1630                 :             :             }
    1631                 :             :         }
    1632                 :             : 
    1633         [ +  + ]:         121 :         uMinAtNumb = ( nMinAtNumb == INCHI_CANON_INFINITY ) ? INCHI_CANON_INFINITY : (AT_NUMB) nMinAtNumb;
    1634                 :             : 
    1635                 :             : #else
    1636                 :             : 
    1637                 :             :         if (v)
    1638                 :             :         {
    1639                 :             :             nCurAtNumb = (int) v - 1;
    1640                 :             :             /* any valid found node must have nAuxRank == uMinAuxRank */
    1641                 :             :             uMinAuxRank = pCD->nAuxRank[nCurAtNumb];
    1642                 :             :         }
    1643                 :             :         else
    1644                 :             :         {
    1645                 :             :             /* any valid found node must have minimal uMinAuxRank from pCD->nAuxRank[] */
    1646                 :             :             uMinAuxRank = INCHI_CANON_INFINITY; /* undefined */
    1647                 :             :         }
    1648                 :             : 
    1649                 :             :         for (; i < W->next; i++)
    1650                 :             :         {
    1651                 :             :             uCurAtNumb = p->AtNumber[(int) i];
    1652                 :             :             nCurAtNumb = (int) uCurAtNumb;
    1653                 :             :             if (uCurAtNumb >= v && !( p->Rank[nCurAtNumb] & rank_mark_bit ))
    1654                 :             :             {
    1655                 :             :                 uCurAuxRank = pCD->nAuxRank[nCurAtNumb];
    1656                 :             :                 if (v)
    1657                 :             :                 {
    1658                 :             :                     /* get next node */
    1659                 :             :                     /* find node with smallest uCurAtNumb among nodes with aux. ranks equal to uMinAuxRank */
    1660                 :             :                     if (uCurAuxRank == uMinAuxRank && uCurAtNumb < uMinAtNumb)
    1661                 :             :                     {
    1662                 :             :                         uMinAtNumb = uCurAtNumb;
    1663                 :             :                     }
    1664                 :             :                 }
    1665                 :             :                 else
    1666                 :             :                 {
    1667                 :             :                     /* get first node */
    1668                 :             :                     /* find node with smallest smallest uCurAtNumb among nodes with smallest aux. ranks */
    1669                 :             :                     if (uMinAuxRank > uCurAuxRank)
    1670                 :             :                     {
    1671                 :             :                         uMinAuxRank = uCurAuxRank;
    1672                 :             :                         uMinAtNumb = uCurAtNumb;
    1673                 :             :                     }
    1674                 :             :                     else
    1675                 :             :                     {
    1676                 :             :                         if (uMinAuxRank == uCurAuxRank && uCurAtNumb < uMinAtNumb)
    1677                 :             :                         {
    1678                 :             :                             uMinAtNumb = uCurAtNumb;
    1679                 :             :                         }
    1680                 :             :                     }
    1681                 :             :                 }
    1682                 :             :             }
    1683                 :             :         }
    1684                 :             : #endif
    1685                 :             :     }
    1686                 :             : 
    1687                 :             :     else
    1688                 :             : #endif /* } USE_AUX_RANKING */
    1689                 :             : 
    1690                 :             :     {
    1691         [ +  + ]:         967 :         for (i = W->first; i < W->next; i++)
    1692                 :             :         {
    1693                 :         694 :             uCurAtNumb = p->AtNumber[(int) i];
    1694   [ +  +  +  -  :         694 :             if (uCurAtNumb >= v && !( p->Rank[(int) uCurAtNumb] & rank_mark_bit ) && uCurAtNumb < uMinAtNumb)
                   +  + ]
    1695                 :             :             {
    1696                 :         222 :                 uMinAtNumb = uCurAtNumb;
    1697                 :             :             }
    1698                 :             :         }
    1699                 :             :     }
    1700                 :             : 
    1701         [ +  + ]:         394 :     if (uMinAtNumb != INCHI_CANON_INFINITY)
    1702                 :             :     {
    1703                 :         322 :         uMinAtNumb++;
    1704                 :             :     }
    1705                 :             : 
    1706                 :             :     INCHI_HEAPCHK
    1707                 :             : 
    1708                 :         394 :     return uMinAtNumb;
    1709                 :             : }
    1710                 :             : 
    1711                 :             : 
    1712                 :             : /****************************************************************************/
    1713                 :          72 : int CellGetNumberOfNodes( Partition *p, Cell *W )
    1714                 :             : {
    1715                 :          72 :     int first = W->first;
    1716                 :          72 :     int next = W->next;
    1717                 :             :     int i, num;
    1718         [ +  + ]:         248 :     for (i = first, num = 0; i < next; i++)
    1719                 :             :     {
    1720         [ +  - ]:         176 :         if (!( rank_mark_bit & p->Rank[(int) p->AtNumber[i]] ))
    1721                 :             :         {
    1722                 :         176 :             num++;
    1723                 :             :         }
    1724                 :             :     }
    1725                 :             : 
    1726                 :             :     INCHI_HEAPCHK
    1727                 :             : 
    1728                 :          72 :     return num;
    1729                 :             : }
    1730                 :             : 
    1731                 :             : 
    1732                 :             : /****************************************************************************/
    1733                 :           0 : int CellIntersectWithSet( CANON_GLOBALS *pCG,
    1734                 :             :                           Partition *p, Cell *W, NodeSet *Mcr, int l )
    1735                 :             : {
    1736                 :           0 :     bitWord *McrBits = Mcr->bitword[l - 1];
    1737                 :           0 :     int first = W->first;
    1738                 :           0 :     int next = W->next;
    1739                 :             :     int i, j, k;
    1740                 :             : 
    1741         [ #  # ]:           0 :     if (first >= next)
    1742                 :             :     {
    1743                 :             :         /* for testing only */
    1744                 :           0 :         return 0;
    1745                 :             :     }
    1746         [ #  # ]:           0 :     for (i = first, k = 0; i < next; i++)
    1747                 :             :     {
    1748                 :           0 :         j = (int) p->AtNumber[i];
    1749         [ #  # ]:           0 :         if (!( McrBits[j / pCG->m_num_bit] & pCG->m_bBit[j % pCG->m_num_bit] ))
    1750                 :             :         {
    1751                 :             :             /* BC: reading uninit memory ???-not examined yet */
    1752                 :           0 :             k += !( p->Rank[j] & rank_mark_bit ); /* for testing only */
    1753                 :           0 :             p->Rank[j] |= rank_mark_bit;
    1754                 :             :         }
    1755                 :             :     }
    1756                 :             :     INCHI_HEAPCHK
    1757                 :             : 
    1758                 :           0 :     return k;
    1759                 :             : }
    1760                 :             : 
    1761                 :             : 
    1762                 :             : /****************************************************************************/
    1763                 :          32 : void CtPartClear( ConTable *Ct, int k )
    1764                 :             : {
    1765                 :             :     int start;
    1766                 :             :     int len;
    1767                 :             :     /* connection table */
    1768         [ -  + ]:          32 :     start = k > 1 ? Ct->nextCtblPos[k - 1] : 0;
    1769                 :          32 :     len = Ct->lenCt - start;
    1770         [ -  + ]:          32 :     if (len > 0)
    1771                 :             :     {
    1772                 :           0 :         memset( Ct->Ctbl + start, 0, ( (long long)Ct->lenCt - (long long)start ) * sizeof( Ct->Ctbl[0] ) ); /* djb-rwth: cast operators added; memset_s C11/Annex K variant? */
    1773                 :             :     }
    1774                 :          32 :     Ct->lenCt = start;
    1775                 :          32 :     Ct->lenPos = k;
    1776                 :             : 
    1777                 :             :     INCHI_HEAPCHK
    1778                 :          32 : }
    1779                 :             : 
    1780                 :             : 
    1781                 :             : /****************************************************************************
    1782                 :             :  Sort neighbors according to ranks in ascending order
    1783                 :             : ****************************************************************************/
    1784                 :        1375 : void insertions_sort_NeighList_AT_NUMBERS2( NEIGH_LIST base,
    1785                 :             :                                             AT_RANK *nRank,
    1786                 :             :                                             AT_RANK max_rj )
    1787                 :             : {
    1788                 :             :     AT_NUMB *i, *j, *pk, tmp, rj;
    1789                 :        1375 :     int k, num = (int) *base++;
    1790         [ +  + ]:        2551 :     for (k = 1, pk = base; k < num; k++, pk++)
    1791                 :             :     {
    1792                 :        1176 :         i = pk;
    1793                 :        1176 :         j = i + 1;
    1794                 :        1176 :         rj = ( rank_mask_bit & nRank[(int) *j] );
    1795         [ +  + ]:        1176 :         if (rj < max_rj)
    1796                 :             :         {
    1797   [ +  +  +  + ]:         455 :             while (j > base && rj < ( rank_mask_bit & nRank[(int) *i] ))
    1798                 :             :             {
    1799                 :          89 :                 tmp = *i;
    1800                 :          89 :                 *i = *j;
    1801                 :          89 :                 *j = tmp;
    1802                 :          89 :                 j = i--;
    1803                 :             :             }
    1804                 :             :         }
    1805                 :             :     }
    1806                 :             : 
    1807                 :             :     INCHI_HEAPCHK
    1808                 :        1375 : }
    1809                 :             : 
    1810                 :             : 
    1811                 :             : /****************************************************************************
    1812                 :             :  may need previous Lambda
    1813                 :             : ****************************************************************************/
    1814                 :         362 : void CtPartFill( Graph *G,
    1815                 :             :                  CANON_DATA *pCD,
    1816                 :             :                  Partition *p,
    1817                 :             :                  ConTable *Ct,
    1818                 :             :                  int k,
    1819                 :             :                  int n,
    1820                 :             :                  int n_tg,
    1821                 :             :                  int n_max
    1822                 :             :                 )
    1823                 :             : {
    1824                 :             :     /*  k = (new index in Ct->nextAtRank[] and Ct->nextCtblPos[]) + 1 */
    1825                 :             : 
    1826                 :             :     int     startCtbl;
    1827                 :             :     int     startAtOrd;
    1828                 :             :     AT_RANK r, rj, nn, j, rj_prev; /* djb-rwth: ignoring LLVM warning as the variable is used */
    1829                 :             :     int     i, m, an_sao;
    1830                 :             : 
    1831                 :             : #ifdef INCHI_CANON_USE_HASH
    1832                 :             :     CtHash  hash = 0;
    1833                 :             : #endif
    1834                 :             : 
    1835                 :             :     /* djb-rwth: removing redundant code */
    1836                 :             : 
    1837                 :             :     INCHI_HEAPCHK
    1838                 :             : 
    1839                 :         362 :     k--;
    1840   [ +  -  +  + ]:         362 :     if (Ct && k) /* djb-rwth: fixing oss-fuzz issue #69612 */
    1841                 :             :     {
    1842                 :         154 :         startCtbl = Ct->nextCtblPos[k - 1];
    1843                 :         154 :         startAtOrd = Ct->nextAtRank[k - 1] - 1;  /* here  p->Rank[p->AtNumber[r-1]] = r */
    1844                 :             :     }
    1845                 :             :     else
    1846                 :             :     {
    1847                 :         208 :         startCtbl = 0;
    1848                 :         208 :         startAtOrd = 0;
    1849                 :             :     }
    1850                 :             : 
    1851                 :             :     /******* Well-defined (by fixed ranks) part of the connection table ************/
    1852                 :             :     /* djb-rwth: fixing oss-fuzz issue #69612 */
    1853         [ -  + ]:         362 :     if (startAtOrd < 0)
    1854                 :             :     {
    1855                 :           0 :         return;
    1856                 :             :     }
    1857                 :             :     /* djb-rwth: fixing oss-fuzz issue #391043585 */
    1858   [ +  -  +  - ]:         362 :     if (startAtOrd < n_max && Ct)
    1859                 :             :     {
    1860                 :         362 :         an_sao = (int)p->AtNumber[startAtOrd];
    1861                 :         362 :         r = (rank_mask_bit & p->Rank[an_sao]);
    1862                 :             : 
    1863   [ +  +  +  + ]:        1737 :         for (i = startAtOrd; i < n_tg && r == (rank_mask_bit & p->Rank[m = (int)p->AtNumber[i]]); i++, r++)
    1864                 :             :         {
    1865                 :        1375 :             Ct->Ctbl[startCtbl++] = r;
    1866                 :        1375 :             insertions_sort_NeighList_AT_NUMBERS2(G[m], p->Rank, r);
    1867                 :        1375 :             nn = G[m][0];   /* number of neighbors */
    1868                 :        1375 :             rj_prev = 0;    /* debug only */ /* djb-rwth: ignoring LLVM warning as the variable is used */
    1869                 :             : 
    1870                 :             : #ifdef INCHI_CANON_USE_HASH
    1871                 :             :             hash = add2crc32(hash, (AT_NUMB)(r + n));
    1872                 :             : #endif
    1873                 :             : 
    1874   [ +  +  +  + ]:        2671 :             for (j = 1; j <= nn && (rj = (rank_mask_bit & p->Rank[(int)G[m][j]])) < r; j++)
    1875                 :             :             {
    1876                 :        1296 :                 Ct->Ctbl[startCtbl++] = rj;
    1877                 :             : 
    1878                 :             : #ifdef INCHI_CANON_USE_HASH
    1879                 :             :                 hash = add2crc32(hash, rj);
    1880                 :             : #endif
    1881                 :             : 
    1882                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    1883                 :             :                 /* debug only */
    1884                 :             :                 if (rj < rj_prev)
    1885                 :             :                 {
    1886                 :             :                     int stop = 1;   /* <BRKPT> */
    1887                 :             :                 }
    1888                 :             : #endif
    1889                 :             : 
    1890                 :        1296 :                 rj_prev = rj; /* djb-rwth: ignoring LLVM warning as the variable is used */
    1891                 :             :             }
    1892                 :             :         }
    1893                 :             :     }
    1894                 :             :     else
    1895                 :             :     {
    1896                 :           0 :         return;
    1897                 :             :     }
    1898                 :             : 
    1899                 :             :     INCHI_HEAPCHK
    1900                 :             : 
    1901                 :             :     /****************** Well-defined part of base hydrogen atoms *******************/
    1902         [ +  - ]:         362 :     if (Ct)
    1903                 :             :     {
    1904   [ +  +  +  - ]:         362 :         if (pCD->NumH && Ct->NumH)
    1905                 :             :         {
    1906                 :          78 :             nn = inchi_min(n, i);
    1907         [ +  + ]:         233 :             for (j = startAtOrd; j < nn; j++)
    1908                 :             :             {
    1909                 :             :                 /* atoms */
    1910                 :         155 :                 Ct->NumH[j] = pCD->NumH[p->AtNumber[j]];
    1911                 :             :             }
    1912         [ +  + ]:         134 :             for (; j < i; j++)
    1913                 :             :             {
    1914                 :             :                 /* t-groups */
    1915                 :          56 :                 int data_pos = n + T_NUM_NO_ISOTOPIC * ((int)p->AtNumber[j] - n);
    1916         [ +  + ]:         168 :                 for (m = 0; m < T_NUM_NO_ISOTOPIC; m++)
    1917                 :             :                 {
    1918                 :         112 :                     Ct->NumH[nn++] = pCD->NumH[data_pos++];
    1919                 :             :                 }
    1920                 :             :             }
    1921                 :          78 :             Ct->lenNumH = nn;
    1922                 :             :         }
    1923                 :             :         else
    1924                 :             :         {
    1925                 :         284 :             Ct->lenNumH = 0;
    1926                 :             :         }
    1927                 :             : 
    1928                 :             :         INCHI_HEAPCHK
    1929                 :             : 
    1930                 :             :             /****************** Well-defined part of fixed hydrogen atoms *******************/
    1931   [ -  +  -  - ]:         362 :             if (pCD->NumHfixed && Ct->NumHfixed)
    1932                 :             :             {
    1933                 :           0 :                 nn = inchi_min(n, i);
    1934         [ #  # ]:           0 :                 for (j = startAtOrd; j < nn; j++)
    1935                 :             :                 {
    1936                 :           0 :                     Ct->NumHfixed[j] = pCD->NumHfixed[p->AtNumber[j]];
    1937                 :             : 
    1938                 :             :                     INCHI_HEAPCHK
    1939                 :             :                 }
    1940                 :             :                 /* Ct->lenNumHfixed = nn; */
    1941                 :             :             }
    1942                 :             :             else
    1943                 :             :             {
    1944                 :             :                 ;/* Ct->lenNumHfixed = 0; */
    1945                 :             :             }
    1946                 :             : 
    1947                 :             :         INCHI_HEAPCHK
    1948                 :             : 
    1949                 :             :             /****************** Well-defined part of isotopic keys ***************************/
    1950   [ -  +  -  - ]:         362 :             if (pCD->iso_sort_key && Ct->iso_sort_key)
    1951                 :             :             {
    1952         [ #  # ]:           0 :                 for (j = startAtOrd; j < i; j++)
    1953                 :             :                 {
    1954                 :           0 :                     Ct->iso_sort_key[j] = pCD->iso_sort_key[p->AtNumber[j]];
    1955                 :             :                 }
    1956                 :           0 :                 Ct->len_iso_sort_key = i;
    1957                 :             :             }
    1958                 :             :             else
    1959                 :             :             {
    1960                 :         362 :                 Ct->len_iso_sort_key = 0;
    1961                 :             :             }
    1962                 :             : 
    1963                 :             :         INCHI_HEAPCHK
    1964                 :             : 
    1965                 :             :             /****************** Well-defined part of isotopic iso_exchg_atnos ***************************/
    1966   [ -  +  -  - ]:         362 :             if (pCD->iso_exchg_atnos && Ct->iso_exchg_atnos)
    1967                 :             :             {
    1968         [ #  # ]:           0 :                 for (j = startAtOrd; j < i; j++)
    1969                 :             :                 {
    1970                 :           0 :                     Ct->iso_exchg_atnos[j] = pCD->iso_exchg_atnos[p->AtNumber[j]];
    1971                 :             :                 }
    1972                 :           0 :                 Ct->len_iso_exchg_atnos = i;
    1973                 :             :             }
    1974                 :             :             else
    1975                 :             :             {
    1976                 :         362 :                 Ct->len_iso_exchg_atnos = 0;
    1977                 :             :             }
    1978                 :             : 
    1979                 :             :         INCHI_HEAPCHK
    1980                 :             : 
    1981                 :             :             /******** Well-defined part of isotopic keys for fixed hydrogen atoms ************/
    1982                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    1983                 :             :             if (pCD->iso_sort_key_Hfixed && Ct->iso_sort_key_Hfixed)
    1984                 :             :             {
    1985                 :             :                 nn = inchi_min(n, i);
    1986                 :             :                 for (j = startAtOrd; j < nn; j++)
    1987                 :             :                 {
    1988                 :             :                     Ct->iso_sort_key_Hfixed[j] = pCD->iso_sort_key_Hfixed[p->AtNumber[j]];
    1989                 :             :                 }
    1990                 :             :                 Ct->len_iso_sort_key_Hfixed = nn;
    1991                 :             :             }
    1992                 :             :             else
    1993                 :             :             {
    1994                 :             :                 Ct->len_iso_sort_key_Hfixed = 0;
    1995                 :             :             }
    1996                 :             : #endif
    1997                 :             : 
    1998                 :             :         INCHI_HEAPCHK
    1999                 :             : 
    2000                 :         362 :             Ct->lenCt = startCtbl; /* not aways increases */
    2001                 :         362 :         Ct->nextCtblPos[k] = startCtbl;
    2002                 :         362 :         Ct->nextAtRank[k] = r;
    2003                 :         362 :         Ct->lenPos = k + 1;
    2004                 :             : 
    2005                 :             :         /* The rest of the CTable */
    2006                 :             : 
    2007                 :             : #ifdef INCHI_CANON_USE_HASH
    2008                 :             :         while (i < n)
    2009                 :             :         {
    2010                 :             :             r = (rank_mask_bit & p->Rank[m = (int)p->AtNumber[i]]);
    2011                 :             :             hash = add2crc32(hash, (AT_NUMB)(r + n));
    2012                 :             :             r++;
    2013                 :             :             insertions_sort_NeighList_AT_NUMBERS2(G[m], p->Rank, r);
    2014                 :             :             nn = G[m][0];
    2015                 :             :             rj_prev = 0; /* debug only */
    2016                 :             :             for (j = 1; j <= nn && (rj = (rank_mask_bit & p->Rank[(int)G[m][j]])) < r; j++)
    2017                 :             :             {
    2018                 :             :                 hash = add2crc32(hash, rj);
    2019                 :             :             }
    2020                 :             :             i++;
    2021                 :             :         }
    2022                 :             :         Ct->hash[k] = hash;
    2023                 :             : #endif
    2024                 :             :     }
    2025                 :             :     INCHI_HEAPCHK
    2026                 :             : }
    2027                 :             : 
    2028                 :             : 
    2029                 :             : /****************************************************************************/
    2030                 :         207 : void CtPartINCHI_CANON_INFINITY( ConTable *Ct, S_CHAR *cmp, int k )
    2031                 :             : {
    2032                 :             :     int     startCtbl;
    2033                 :             :     /*int     startAtOrd;*/
    2034                 :         207 :     k--;
    2035         [ +  - ]:         207 :     if (k)
    2036                 :             :     {
    2037                 :         207 :         startCtbl = Ct->nextCtblPos[k - 1];
    2038                 :             :         /*startAtOrd = Ct->nextAtRank[k-1]-1;*/  /* here  p->Rank[p->AtNumber[r-1]] = r */
    2039         [ -  + ]:         207 :         if (cmp)
    2040                 :             :         {
    2041                 :           0 :             memset( cmp, 0, k * sizeof( cmp[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    2042                 :             :         }
    2043                 :             :     }
    2044                 :             :     else
    2045                 :             :     {
    2046                 :           0 :         startCtbl = 0;
    2047                 :             :         /*startAtOrd = 0;*/
    2048                 :             :     }
    2049   [ +  -  +  - ]:         207 :     if (!startCtbl || Ct->Ctbl[startCtbl - 1] != EMPTY_CT)
    2050                 :             :     {
    2051                 :         207 :         Ct->Ctbl[startCtbl] = EMPTY_CT;
    2052                 :             :     }
    2053                 :             : 
    2054                 :             :     INCHI_HEAPCHK
    2055                 :         207 : }
    2056                 :             : 
    2057                 :             : 
    2058                 :             : /****************************************************************************
    2059                 :             :  Return value:
    2060                 :             :   -1 <=> *Lambda1 < *Lambda2
    2061                 :             :    0 <=> *Lambda1 = *Lambda2
    2062                 :             :   +1 <=> *Lambda1 > *Lambda2
    2063                 :             : 
    2064                 :             :   Input: k+1 = value of level at which the comparison is executed
    2065                 :             :                (that is, in the calling program k(caller) = k+1)
    2066                 :             : 
    2067                 :             :   Stars (*) below mark the differences:
    2068                 :             : 
    2069                 :             :   bSplitTautCompare != 0 => directed graph; compare:
    2070                 :             :                    non-tautomeric part of CT in layer 0; (*)
    2071                 :             :                    non-tautomeric H          in layer 1; (*)
    2072                 :             :                    tautomeric part of CT & H in layer 2; (*)
    2073                 :             :                    fixed H                   in layer 3;
    2074                 :             :                    isotopic atoms, non-taut
    2075                 :             :                                H & t-groups  in layer 4;
    2076                 :             :                    fixed isotopic H          in layer 5; <- move to layer 4
    2077                 :             : 
    2078                 :             :   bSplitTautCompare == 0 => undirected graph; compare:
    2079                 :             :                    full CT                   in Layer 0; (*)
    2080                 :             :                    taut and non-taut H       in Layer 1; (*)
    2081                 :             :                    * nothing *               in layer 2; (*)
    2082                 :             :                    fixed H                   in layer 3;
    2083                 :             :                    isotopic atoms, non-taut
    2084                 :             :                                H & t-groups  in layer 4;
    2085                 :             :                    fixed isotopic H          in layer 5; <- move to layer 4
    2086                 :             : 
    2087                 :             : ****************************************************************************/
    2088                 :         365 : int CtPartCompare( ConTable *Ct1,
    2089                 :             :                    ConTable *Ct2,
    2090                 :             :                    S_CHAR *cmp,
    2091                 :             :                    kLeast *kLeastForLayer,
    2092                 :             :                    int k,
    2093                 :             :                    int bOnlyCommon,
    2094                 :             :                    int bSplitTautCompare )
    2095                 :             : {
    2096                 :             :     int     startCt1, endCt1, startCt2, endCt2; /*endCt,*/
    2097                 :             :     int     startAt1, endAt1, startAt2, endAt2; /*endCt,*/
    2098                 :         365 :     int     midCt /* end of atoms only Ct */, midNumH = 0 /* end of atoms only NumH */, maxVert;
    2099                 :             :     int     diff, i, k1, k2, lenNumH, /*mid_iso_sort_key,*/ midAt; /* djb-rwth: ignoring LLVM warning: variables used */
    2100                 :         365 :     int     nLayer = 0;
    2101                 :             : 
    2102                 :         365 :     k--;
    2103                 :         365 :     i = -1;
    2104                 :             : 
    2105                 :             :     /* set kLeastForLayer[nLayer].k = (k+1) or -(k+1)
    2106                 :             :            kLeastForLayer[nLayer].i = iDiff
    2107                 :             :         if all the conditions are met:
    2108                 :             :         1) kLeastForLayer[nLayer].k = 0
    2109                 :             :         2) diff==0 for all layers < nLayer
    2110                 :             : 
    2111                 :             :         sign:
    2112                 :             :         if the final diff < 0 then kLeastForLayer[nLayer].k = -(k+1) else
    2113                 :             :         if the final diff > 0 then kLeastForLayer[nLayer].k = +(k+1)
    2114                 :             : 
    2115                 :             :         k+1 instead of k takes into account k--; statememt above)
    2116                 :             : 
    2117                 :             :         meaning:
    2118                 :             :         ========
    2119                 :             :         abs(kLeastForLayer[nLayer].k) is the greatest level k at which
    2120                 :             :         difference at layer nLayer are zeroes of hidden by differences in smaller nLayer.
    2121                 :             : 
    2122                 :             :         "Hidden by difference in smaller level" means that nLayer of comparison
    2123                 :             :         has not been reached because the difference was discovered at a previous layer.
    2124                 :             : 
    2125                 :             : 
    2126                 :             :         Lambda vs zf_zeta comparison
    2127                 :             :         =============================================
    2128                 :             :         accept only diff == 0
    2129                 :             : 
    2130                 :             :         Lambda vs pzb_rho and pzb_rho_fix comparison
    2131                 :             :         =============================================
    2132                 :             :         Maintain kLeastForLayer[] and kLeastForLayerFix[]
    2133                 :             : 
    2134                 :             :         The algorithm provides that pzb_rho(m-1) < pzb_rho(m) <= pzb_rho_fix
    2135                 :             : 
    2136                 :             :         Definition: pzb_rho(m-1) < pzb_rho(m) means that
    2137                 :             :         -----------------------------------------------
    2138                 :             :         pzb_rho(m-1)[nLayerCurr] == pzb_rho(m)[nLayerCurr] for nLayerCurr = 0..nLayerDiff-1
    2139                 :             :         pzb_rho(m-1)[nLayerDiff] <  pzb_rho(m)[nLayerDiff]
    2140                 :             : 
    2141                 :             :         Definition: pzb_rho(m-1)[nLayerDiff] <  pzb_rho(m)[nLayerDiff] means that
    2142                 :             :         -------------------------------------------------------------------------
    2143                 :             :         pzb_rho(m-1)[nLayerDiff][i]     == pzb_rho(m)[nLayerDiff][i] for i=0..iDdiff-1
    2144                 :             :         pzb_rho(m-1)[nLayerDiff][iDdiff] < pzb_rho(m)[nLayerDiff][iDdiff]
    2145                 :             : 
    2146                 :             :         This defines nLayerDiff(pzb1, pzb2) where pszb1 = pzb_rho(a), pzb2=pzb_rho(b) (a<b) or pzb_rho_fix
    2147                 :             :                and   iDdiff    (pzb1, pzb2).
    2148                 :             :         In case pzb_rho(m)[nLayerCurr] == pzb_rho_fix[nLayerCurr] for all non-NULL nLayerCurr in pzb_rho_fix,
    2149                 :             :            nLayerDiff(pzb_rho(m), pzb_rho_fix) = the first layer in pzb_rho(m) not present in pzb_rho_fix
    2150                 :             :            iDdiff    (pzb_rho(m), pzb_rho_fix) = -1
    2151                 :             :         Case when such a layer does not exist means program error
    2152                 :             : 
    2153                 :             :         Suppose L_rho = nLayerDiff(Lambda, pzb_rho(m))
    2154                 :             :                 L_fix = nLayerDiff(Lambda, pzb_rho_fix)
    2155                 :             :                 I_rho = iDdiff    (Lambda, pzb_rho(m))
    2156                 :             :                 I_fix = iDdiff    (Lambda, pzb_rho_fix)
    2157                 :             :                 kLeastForLayer determined from Lambda vs pzb_rho(m) comparison
    2158                 :             :         Then:
    2159                 :             : 
    2160                 :             :         1. Comparison Lambda vs pzb_rho_fix before reaching discrete partition
    2161                 :             :         ----------------------------------------------------------------------
    2162                 :             :         a)    0 < abs(kLeastForLayerFix[L_fix].k) <= k-1 (* in this case I_fix >= 0 *)  &&
    2163                 :             :               ((L_fix < L_rho) || (L_fix == L_rho && I_fix < I_rho))
    2164                 :             :               =>
    2165                 :             :               qzb_rho_fix = kLeastForLayerFix[L_fix].k if prevoiusly qzb_rho_fix == 0
    2166                 :             : 
    2167                 :             :         b)    otherwise do not change qzb_rho_fix, except the following:
    2168                 :             : 
    2169                 :             :         c)    Special case L_rho == L_fix && I_rho == I_fix. Let L=L_rho, I = I_rho.
    2170                 :             : 
    2171                 :             :               Compare 3 valirs: Lambda[L][I], pzb_rho(m)[L][I], pzb_rho_fix[L][I]
    2172                 :             :               The algorithm provides pzb_rho(m)[L][I] < pzb_rho_fix[L][I]
    2173                 :             :               (pzb_rho(m)[L][I]==pzb_rho_fix[L][I] <=> pzb_rho(m)[L][I]==pzb_rho_fix[L][I]
    2174                 :             :                is impossible by construction)
    2175                 :             :               There are 3 possibilities:
    2176                 :             :               c1) Lambda[L][I]     < pzb_rho(m)[L][I]  < pzb_rho_fix[L][I] <=>
    2177                 :             :                   kLeastForLayer[L].k  < 0 && kLeastForLayerFix[L].k < 0
    2178                 :             :                   => qzb_rho := kLeastForLayer[L].k, reject too small Lambda
    2179                 :             :               c2) pzb_rho(m)[L][I] < Lambda[L][I]      < pzb_rho_fix[L][I]
    2180                 :             :                   kLeastForLayer[L].k  > 0 && kLeastForLayerFix[L].k < 0
    2181                 :             :                   => qzb_rho := kLeastForLayer[L].k, accept Lambda, rho:=nu
    2182                 :             :               c3) pzb_rho(m)[L][I] < pzb_rho_fix[L][I] < Lambda[L][I]
    2183                 :             :                   kLeastForLayer[L].k  > 0 && kLeastForLayerFix[L].k > 0
    2184                 :             :                   => qzb_rho_fix := kLeastForLayerFix[L].k, reject too big Lambda
    2185                 :             : 
    2186                 :             :               Case
    2187                 :             :                   kLeastForLayer[L].k  < 0 && kLeastForLayerFix[L].k > 0 is impossible
    2188                 :             :                   because it means
    2189                 :             :                   pzb_rho_fix < Lambda < pzb_rho(m) <=> pzb_rho_fix < pzb_rho(m)
    2190                 :             : 
    2191                 :             : 
    2192                 :             :             Case (c3) occurs in case of (a)
    2193                 :             :             Case (c1)
    2194                 :             : 
    2195                 :             :         2. Comparison Lambda vs pzb_rho before reaching discrete partition
    2196                 :             :         ----------------------------------------------------------------------
    2197                 :             :         a) (L_rho < L_fix) || (L_rho == L_fix && I_rho < I_fix)  =>
    2198                 :             : 
    2199                 :             :            Lambda differs from pzb_rho(m) in the part of pzb_rho(m) that will never change
    2200                 :             :            qzb_rho = kLeastForLayer[L_rho].k; reject Labmda or accept pzb_rho(m+1):=Labmda
    2201                 :             : 
    2202                 :             :         b) (L_rho == L_fix && I_rho > I_fix) && kLeastForLayer[L_rho].k < 0
    2203                 :             :            Lambda < pzb_rho(m), therefore
    2204                 :             :            qzb_rho = kLeastForLayer[L_rho].k; reject Labmda
    2205                 :             : 
    2206                 :             :         c) (L_rho > L_fix) =>
    2207                 :             :            qzb_rho := 0 because more significant difference may be discovered
    2208                 :             :            in layer < L_rho later. The final comparison may be needed at the
    2209                 :             :            level of discrete partition.
    2210                 :             : 
    2211                 :             : 
    2212                 :             :     */
    2213                 :             : 
    2214         [ -  + ]:         365 :     if (cmp)
    2215                 :             :     {
    2216   [ #  #  #  # ]:           0 :         for (i = 0; i <= k && !cmp[i]; i++)
    2217                 :             :         {
    2218                 :             :             ;
    2219                 :             :         }
    2220         [ #  # ]:           0 :         if (i < k)
    2221                 :             :         {
    2222                 :           0 :             cmp[k] = cmp[i];
    2223                 :           0 :             return (int) cmp[i];
    2224                 :             :         }
    2225                 :             :     }
    2226                 :             : 
    2227                 :         365 :     k1 = Ct1->lenPos - 1; /* djb-rwth: ignoring LLVM warning: variable used */
    2228                 :         365 :     k2 = Ct2->lenPos - 1; /* djb-rwth: ignoring LLVM warning: variable used */
    2229                 :             : 
    2230                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    2231                 :             :     if (k > k1 || k > k2)
    2232                 :             :     {
    2233                 :             :         int stop = 1;
    2234                 :             :     }
    2235                 :             : #endif
    2236                 :             : 
    2237                 :         365 :     diff = 0; /* djb-rwth: ignoring LLVM warning: variable used */
    2238                 :             : 
    2239         [ +  + ]:         365 :     if (k)
    2240                 :             :     {
    2241                 :         285 :         startCt1 = Ct1->nextCtblPos[k - 1];
    2242                 :         285 :         startCt2 = Ct2->nextCtblPos[k - 1];
    2243                 :         285 :         startAt1 = Ct1->nextAtRank[k - 1] - 1;
    2244                 :         285 :         startAt2 = Ct2->nextAtRank[k - 1] - 1;
    2245                 :             :     }
    2246                 :             :     else
    2247                 :             :     {
    2248                 :          80 :         startCt1 = startCt2 = 0;
    2249                 :          80 :         startAt1 = startAt2 = 0;
    2250                 :             :     }
    2251                 :             : 
    2252                 :         365 :     endCt1 = Ct1->nextCtblPos[k];
    2253                 :         365 :     endCt2 = Ct2->nextCtblPos[k];
    2254                 :         365 :     endAt1 = (int) Ct1->nextAtRank[k] - 1;
    2255                 :         365 :     endAt2 = (int) Ct2->nextAtRank[k] - 1;
    2256                 :             : 
    2257                 :         365 :     maxVert = inchi_min( Ct1->maxVert, Ct2->maxVert );
    2258                 :             : 
    2259                 :             : #ifdef INCHI_CANON_USE_HASH
    2260                 :             :     if (!diff)
    2261                 :             :     {
    2262                 :             :         if (Ct1->hash[k] > Ct2->hash[k])
    2263                 :             :             diff = 1;
    2264                 :             :         else
    2265                 :             :             if (Ct1->hash[k] < Ct2->hash[k])
    2266                 :             :                 diff = -1;
    2267                 :             :     }
    2268                 :             :     if (diff)
    2269                 :             :     {
    2270                 :             :         goto done;
    2271                 :             :     }
    2272                 :             : #endif
    2273                 :             : 
    2274                 :             :     /************************** lengths **************************************************/
    2275         [ -  + ]:         365 :     if ((diff = -( startCt1 - startCt2 ))) /* djb-rwth: addressing LLVM warning */
    2276                 :             :     {
    2277                 :             :         /* comparing two INCHI_CANON_INFINITY terminations */
    2278         [ #  # ]:           0 :         if (bOnlyCommon &&
    2279   [ #  #  #  # ]:           0 :              startCt1 >= Ct1->nLenCTAtOnly && startCt2 >= Ct2->nLenCTAtOnly &&
    2280   [ #  #  #  # ]:           0 :              Ct1->Ctbl[startCt1] == EMPTY_CT && Ct2->Ctbl[startCt2] == EMPTY_CT)
    2281                 :             :         {
    2282                 :           0 :             return 0;
    2283                 :             :         }
    2284         [ #  # ]:           0 :         if (bOnlyCommon)
    2285                 :             :         {
    2286                 :           0 :             startCt1 = inchi_min( startCt1, startCt2 ); /* djb-rwth: removing redundant code */
    2287                 :           0 :             startAt1 = startAt2 = inchi_min( startAt1, startAt2 );
    2288         [ #  # ]:           0 :             if (Ct1->lenCt == Ct2->lenCt)
    2289                 :             :             {
    2290                 :           0 :                 endCt1 = endCt2 = inchi_max( endCt1, endCt2 );
    2291                 :           0 :                 endAt1 = endAt2 = inchi_max( endAt1, endAt2 );
    2292                 :             :             }
    2293                 :             : 
    2294                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    2295                 :             :             else
    2296                 :             :             {
    2297                 :             :                 int stop = 1;
    2298                 :             :             }
    2299                 :             : #endif
    2300                 :             :         }
    2301                 :             :         else
    2302                 :             :         /* comparing (taut tail) vs INCHI_CANON_INFINITY termination -- ??? */
    2303         [ #  # ]:           0 :             if (startCt1 > startCt2 &&
    2304         [ #  # ]:           0 :                  Ct1->maxVert > Ct2->maxVert &&
    2305         [ #  # ]:           0 :                  startAt2 == Ct2->maxVert)
    2306                 :             :             {
    2307                 :           0 :                 return 0;
    2308                 :             :             }
    2309                 :             :             else
    2310                 :             :             {
    2311                 :           0 :                 goto done;
    2312                 :             :             }
    2313                 :             :     }
    2314                 :             : 
    2315                 :         365 :     lenNumH = Ct1->lenNumH;
    2316                 :             :     /* djb-rwth: removing redundant code */
    2317                 :             : 
    2318         [ +  + ]:         365 :     if ((diff = -( endCt1 - endCt2 ))) /* djb-rwth: addressing LLVM warning */
    2319                 :             :     {
    2320                 :             :         /* negative sign reproduces results for NSC=28393 */
    2321         [ +  - ]:          28 :         if (bOnlyCommon)
    2322                 :             :         {
    2323                 :          28 :             endCt1 = inchi_min( endCt1, endCt2 ); /* djb-rwth: removing redundant code */
    2324                 :          28 :             endAt1 = endAt2 = inchi_min( endAt1, endAt2 );
    2325                 :          28 :             lenNumH = inchi_min( Ct1->lenNumH, Ct2->lenNumH );
    2326                 :             :             /* djb-rwth: removing redundant code */
    2327                 :             :         }
    2328                 :             :         else
    2329                 :             :         {
    2330                 :             :             /* take care of case when comparing tautomeric vs non-tautomeric:
    2331                 :             :             since (taut)->maxVert > (non-taut)->maxVert, --???
    2332                 :             :             (taut)->maxlenCt  > (non-taut)->maxlenCt     --!!!
    2333                 :             :             compare up to min out of the two, ignoring INCHI_CANON_INFINITY in the last position */
    2334   [ #  #  #  # ]:           0 :             if (endCt1 > endCt2 && Ct1->maxlenCt > Ct2->maxlenCt)
    2335                 :             :             {
    2336         [ #  # ]:           0 :                 if (endAt2 == Ct2->maxVert + 1)
    2337                 :             :                 {
    2338                 :             :                     /* remove INCHI_CANON_INFINITY termination of the shorter CT */
    2339                 :             :                     /* should never happen */
    2340                 :           0 :                     endAt2--;
    2341                 :           0 :                     lenNumH = endAt1 = endAt2; /* djb-rwth: removing redundant code */
    2342                 :           0 :                     endCt2--;
    2343                 :           0 :                     endCt1 = endCt2;
    2344                 :           0 :                     diff = 0; /* djb-rwth: ignoring LLVM warning: value used? */
    2345                 :             :                 }
    2346         [ #  # ]:           0 :                 else if (endAt2 == Ct2->maxVert)
    2347                 :             :                 {
    2348                 :             :                     /* remove INCHI_CANON_INFINITY termination of CT */
    2349                 :           0 :                     lenNumH = endAt1 = endAt2; /* djb-rwth: removing redundant code */
    2350                 :           0 :                     endCt1 = endCt2;
    2351                 :           0 :                     diff = 0; /* djb-rwth: ignoring LLVM warning: value used? */
    2352                 :             :                 }
    2353                 :             :                 else
    2354                 :             :                 {
    2355                 :           0 :                     goto done;
    2356                 :             :                 }
    2357                 :             :             }
    2358                 :             :             else
    2359                 :             :             {
    2360                 :           0 :                 goto done;
    2361                 :             :             }
    2362                 :             :         }
    2363                 :             :     }
    2364                 :             : 
    2365         [ +  + ]:         365 :     if (bSplitTautCompare)
    2366                 :             :     {
    2367                 :         171 :         midCt = inchi_min( Ct1->nLenCTAtOnly, Ct2->nLenCTAtOnly );
    2368         [ +  + ]:         171 :         if (midCt > endCt1)
    2369                 :             :         {
    2370                 :         101 :             midCt = endCt1;
    2371                 :             :         }
    2372                 :         171 :         midAt = inchi_min( maxVert, endAt1 );
    2373                 :             :     }
    2374                 :             :     else
    2375                 :             :     {
    2376                 :         194 :         midCt = endCt1;
    2377                 :         194 :         midAt = endAt1;
    2378                 :             :     }
    2379                 :             : 
    2380                 :             : 
    2381                 :             :     /*endCt   = min(endCt1, endCt2);*/
    2382                 :             :     /*************************************************************************/
    2383                 :             :     /************ layer 0: connection table without tautomeric groups ********/
    2384                 :             :     /*************************************************************************/
    2385                 :             : 
    2386   [ +  +  +  - ]:        2477 :     for (i = startCt1; i < midCt && Ct1->Ctbl[i] == Ct2->Ctbl[i]; i++)
    2387                 :             :     /*for ( i = startCt1; i < endCt && !(diff = (int)Ct1->Ctbl[i] - (int)Ct2->Ctbl[i]); i ++ )*/
    2388                 :             :     {
    2389                 :             :         ;
    2390                 :             :     }
    2391                 :             : 
    2392         [ -  + ]:         365 :     if (i < midCt)
    2393                 :             :     {
    2394                 :           0 :         diff = (int) Ct1->Ctbl[i] - (int) Ct2->Ctbl[i];
    2395                 :           0 :         goto done;
    2396                 :             :     }
    2397                 :             : 
    2398                 :             :     /*************************************************************************/
    2399                 :             :     /******** layer 1 NumH: H atoms without tautomeric H *********************/
    2400                 :             :     /*************************************************************************/
    2401                 :             : 
    2402                 :         365 :     nLayer++;
    2403                 :             : 
    2404                 :             :     /*============= check limits for consistency  ==========*/
    2405         [ -  + ]:         365 :     if ((diff = -( startAt1 - startAt2 ))) /* djb-rwth: addressing LLVM warning */
    2406                 :             :     {
    2407                 :           0 :         goto done;   /* should not happen */
    2408                 :             :     }
    2409         [ -  + ]:         365 :     if ((diff = -( endAt1 - endAt2 ))) /* djb-rwth: addressing LLVM warning */
    2410                 :             :     {
    2411                 :           0 :         goto done;   /* should not happen */
    2412                 :             :     }
    2413                 :             : 
    2414                 :             :     /*============= comparison =============================*/
    2415   [ +  +  +  - ]:         365 :     if (Ct1->NumH && Ct2->NumH)
    2416                 :             :     {
    2417         [ +  + ]:         171 :         if (endAt1 < maxVert)
    2418                 :             :         {
    2419                 :         101 :             midNumH = lenNumH = endAt1;
    2420                 :             :         }
    2421         [ +  - ]:          70 :         else if (bSplitTautCompare)
    2422                 :             :         {
    2423                 :          70 :             midNumH = maxVert;
    2424                 :             :         }
    2425                 :             :         else
    2426                 :             :         {
    2427                 :           0 :             midNumH = lenNumH;
    2428                 :             :         }
    2429                 :             : 
    2430                 :             :         /* lenNumH = (endAt2 >= maxVert)? lenNumH : endAt2; */
    2431                 :             :         /* endAt1 = (endAt2 == n)? lenNumH : endAt2; */
    2432                 :             : 
    2433   [ +  +  +  - ]:         527 :         for (i = startAt1; i < midNumH && Ct1->NumH[i] == Ct2->NumH[i]; i++)
    2434                 :             :         {
    2435                 :             :             ;
    2436                 :             :         }
    2437         [ -  + ]:         171 :         if (i < midNumH)
    2438                 :             :         {
    2439                 :           0 :             diff = (int) Ct1->NumH[i] - (int) Ct2->NumH[i];
    2440                 :           0 :             goto done;
    2441                 :             :         }
    2442                 :             :     }
    2443                 :             : 
    2444                 :             : 
    2445                 :             :     /*************************************************************************/
    2446                 :             :     /************** layer 2: tautomeric part of CT and tautomeric H **********/
    2447                 :             :     /*************************************************************************/
    2448                 :         365 :     nLayer++;
    2449   [ +  +  +  - ]:         653 :     for (i = midCt; i < endCt1 && Ct1->Ctbl[i] == Ct2->Ctbl[i]; i++)
    2450                 :             :     {
    2451                 :             :         ; /* compare tautomeric groups part of CT */
    2452                 :             :     }
    2453         [ -  + ]:         365 :     if (i < endCt1)
    2454                 :             :     {
    2455                 :           0 :         diff = (int) Ct1->Ctbl[i] - (int) Ct2->Ctbl[i];
    2456                 :           0 :         goto done;
    2457                 :             :     }
    2458   [ +  +  +  - ]:         365 :     if (Ct1->NumH && Ct2->NumH)
    2459                 :             :     {
    2460   [ +  +  +  - ]:         347 :         for (i = midNumH; i < lenNumH && Ct1->NumH[i] == Ct2->NumH[i]; i++)
    2461                 :             :         {
    2462                 :             :             ; /* compare tautomeric H */
    2463                 :             :         }
    2464         [ -  + ]:         171 :         if (i < lenNumH)
    2465                 :             :         {
    2466                 :           0 :             diff = (int) Ct1->NumH[i] - (int) Ct2->NumH[i];
    2467                 :           0 :             i += endCt1 - midCt;
    2468                 :           0 :             goto done;
    2469                 :             :         }
    2470                 :             :     }
    2471                 :             : 
    2472                 :             : 
    2473                 :             :     /*************************************************************************/
    2474                 :             :     /************** layer 3: Fixed H atoms ***********************************/
    2475                 :             :     /*************************************************************************/
    2476                 :         365 :     nLayer++;
    2477   [ -  +  -  - ]:         365 :     if (Ct1->NumHfixed && Ct2->NumHfixed)
    2478                 :             :     {
    2479   [ #  #  #  # ]:           0 :         for (i = startAt1; i < midAt && Ct1->NumHfixed[i] == Ct2->NumHfixed[i]; i++)
    2480                 :             :         {
    2481                 :             :             ;
    2482                 :             :         }
    2483         [ #  # ]:           0 :         if (i < midAt)
    2484                 :             :         {
    2485                 :           0 :             diff = (int) Ct1->NumHfixed[i] - (int) Ct2->NumHfixed[i];
    2486                 :           0 :             goto done;
    2487                 :             :         }
    2488                 :             :     }
    2489                 :             : 
    2490                 :             : 
    2491                 :             :     /*************************************************************************/
    2492                 :             :     /************** layer 4: isotopic atoms H, incl. tautomeric **************/
    2493                 :             :     /*************************************************************************/
    2494                 :         365 :     nLayer++;
    2495   [ -  +  -  - ]:         365 :     if (Ct1->iso_sort_key && Ct2->iso_sort_key)
    2496                 :             :     {
    2497   [ #  #  #  # ]:           0 :         for (i = startAt1; i < endAt1 && Ct1->iso_sort_key[i] == Ct2->iso_sort_key[i]; i++)
    2498                 :             :             ;
    2499         [ #  # ]:           0 :         if (i < endAt1)
    2500                 :             :         {
    2501         [ #  # ]:           0 :             diff = Ct1->iso_sort_key[i] > Ct2->iso_sort_key[i] ? 1 : -1;
    2502                 :           0 :             goto done;
    2503                 :             :         }
    2504                 :             :     }
    2505   [ +  -  -  - ]:         365 :     if (Ct1->iso_exchg_atnos && Ct2->len_iso_exchg_atnos)
    2506                 :             :     {
    2507   [ #  #  #  # ]:           0 :         for (i = startAt1; i < endAt1 && Ct1->iso_exchg_atnos[i] == Ct2->iso_exchg_atnos[i]; i++)
    2508                 :             :         {
    2509                 :             :             ;
    2510                 :             :         }
    2511         [ #  # ]:           0 :         if (i < endAt1)
    2512                 :             :         {
    2513         [ #  # ]:           0 :             diff = Ct1->iso_exchg_atnos[i] > Ct2->iso_exchg_atnos[i] ? 1 : -1;
    2514                 :           0 :             goto done;
    2515                 :             :         }
    2516                 :             :     }
    2517                 :             : 
    2518                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    2519                 :             : 
    2520                 :             :     /*************************************************************************/
    2521                 :             :     /************** layer 6: Fixed isotopic H atoms **************************/
    2522                 :             :     /*************************************************************************/
    2523                 :             :     nLayer++;
    2524                 :             :     if (Ct1->iso_sort_key_Hfixed && Ct2->iso_sort_key_Hfixed)
    2525                 :             :     {
    2526                 :             :         for (i = startAt1; i < midAt && Ct1->iso_sort_key_Hfixed[i] == Ct2->iso_sort_key_Hfixed[i]; i++)
    2527                 :             :         {
    2528                 :             :             ;
    2529                 :             :         }
    2530                 :             :         if (i < midAt)
    2531                 :             :         {
    2532                 :             :             diff = Ct1->iso_sort_key_Hfixed[i] > Ct2->iso_sort_key_Hfixed[i] ? 1 : -1;
    2533                 :             :             goto done;
    2534                 :             :         }
    2535                 :             :     }
    2536                 :             : #endif
    2537                 :             : 
    2538                 :             : 
    2539                 :             : 
    2540                 :         365 : done:
    2541                 :             : 
    2542                 :             : #ifdef INCHI_CANON_MIN
    2543                 :         365 :     diff = -diff;
    2544                 :             : #endif
    2545                 :             : 
    2546         [ -  + ]:         365 :     if (diff)
    2547                 :             :     {
    2548         [ #  # ]:           0 :         diff = ( diff > 0 ) ? ( nLayer + 1 ) : -( nLayer + 1 ); /* return the discovered difference layer number >= 1 */
    2549         [ #  # ]:           0 :         if (kLeastForLayer)
    2550                 :             :         {
    2551                 :             : 
    2552                 :             : #if ( bRELEASE_VERSION != 1 )
    2553                 :             :             if (abs( kLeastForLayer[nLayer].k ) > k + 1)
    2554                 :             :             { /* for debug only */
    2555                 :             :                 int stop = 1; /* <BRKPT> */
    2556                 :             :             }
    2557                 :             : #endif
    2558                 :             : 
    2559         [ #  # ]:           0 :             if (!kLeastForLayer[nLayer].k)
    2560                 :             :             {
    2561         [ #  # ]:           0 :                 kLeastForLayer[nLayer].k = ( diff > 0 ) ? ( k + 1 ) : -( k + 1 );
    2562                 :           0 :                 kLeastForLayer[nLayer].i = i;
    2563                 :             :             }
    2564         [ #  # ]:           0 :             if (nLayer /* && !bOnlyCommon */)
    2565                 :             :             {
    2566                 :           0 :                 diff = 0;
    2567                 :             :             }
    2568                 :             :         }
    2569                 :             :     }
    2570                 :             : 
    2571                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    2572                 :             :     else
    2573                 :             :     {
    2574                 :             :         int stop = 1;  /* for debug only */
    2575                 :             :     }
    2576                 :             : #endif
    2577                 :             : 
    2578         [ -  + ]:         365 :     if (cmp)
    2579                 :             :     {
    2580   [ #  #  #  # ]:           0 :         cmp[k] = ( diff > 0 ) ? 1 : ( diff < 0 ) ? -1 : 0;
    2581                 :             :     }
    2582                 :             : 
    2583                 :         365 :     return diff;
    2584                 :             : }
    2585                 :             : 
    2586                 :             : 
    2587                 :             : /**************************************************************************************************************/
    2588                 :          94 : int CtFullCompare( ConTable *Ct1,
    2589                 :             :                    ConTable *Ct2,
    2590                 :             :                    int bOnlyCommon,
    2591                 :             :                    int bSplitTautCompare )
    2592                 :             : {
    2593                 :             :     int     startCt1, endCt1, endCt2; /*endCt,*/
    2594                 :             :     int     startAt1, endAt1, endAt2; /*endCt,*/
    2595                 :             :     int     midCt   /* end of atoms only in Ctbl */,
    2596                 :          94 :         midNumH = 0 /* end of atoms only NumH */,
    2597                 :             :         midAt   /* end of atoms only */; /* djb-rwth: ignoring LLVM warning: variable used */
    2598                 :          94 :     int     diff = 0, i, k1, k2, lenNumH1, lenNumH2, maxVert /* min num atoms */;
    2599                 :             :     int     len_iso_sort_key1, len_iso_sort_key2 /*, mid_iso_sort_key*/;
    2600                 :          94 :     int     nLayer = 0;
    2601                 :             : 
    2602                 :          94 :     k1 = Ct1->lenPos - 1;
    2603                 :          94 :     k2 = Ct2->lenPos - 1;
    2604                 :             : 
    2605                 :             :     /* djb-rwth: removing redundant code */
    2606                 :             : 
    2607                 :          94 :     startCt1 = 0; /* djb-rwth: removing redundant code */
    2608                 :          94 :     startAt1 = 0; /* djb-rwth: removing redundant code */
    2609                 :             : 
    2610                 :          94 :     endCt1 = Ct1->nextCtblPos[k1];
    2611                 :          94 :     endCt2 = Ct2->nextCtblPos[k2];
    2612                 :          94 :     endAt1 = (int) Ct1->nextAtRank[k1] - 1;
    2613                 :          94 :     endAt2 = (int) Ct2->nextAtRank[k2] - 1;
    2614                 :             : 
    2615                 :          94 :     maxVert = inchi_min( Ct1->maxVert, Ct2->maxVert );
    2616                 :             : 
    2617         [ +  + ]:          94 :     if (bOnlyCommon)
    2618                 :             :     {
    2619                 :          21 :         endCt1 = inchi_min( endCt1, endCt2 );
    2620                 :          21 :         endCt1 = endCt2 = inchi_min( endCt1, Ct1->lenCt );
    2621                 :          21 :         endAt1 = inchi_min( endAt1, endAt2 ); /* djb-rwth: removing redundant code */
    2622                 :             : 
    2623   [ +  +  +  - ]:          21 :         if (Ct1->Ctbl[endCt1] == EMPTY_CT || Ct2->Ctbl[endCt1] == EMPTY_CT) /* djb-rwth: redundant conditions removed */
    2624                 :             :         {
    2625                 :          21 :             endCt1 = endCt2 = endCt1 - 1;
    2626                 :             :         }
    2627                 :             :         /* djb-rwth: removing redundant code */
    2628                 :          21 :         lenNumH1 =
    2629                 :          21 :         lenNumH2 = inchi_min( Ct1->lenNumH, Ct2->lenNumH );
    2630                 :             : 
    2631                 :             :         /* djb-rwth: removing redundant code */
    2632                 :          21 :         len_iso_sort_key1 =
    2633                 :          21 :         len_iso_sort_key2 = inchi_min( Ct1->len_iso_sort_key, Ct1->len_iso_sort_key );
    2634                 :             :     }
    2635                 :             :     else
    2636                 :             :     {
    2637         [ -  + ]:          73 :         if (Ct1->Ctbl[endCt1 - 1] == EMPTY_CT)
    2638                 :             :         {
    2639                 :           0 :             endCt1--;
    2640                 :             :         }
    2641         [ -  + ]:          73 :         if (Ct2->Ctbl[endCt2 - 1] == EMPTY_CT)
    2642                 :             :         {
    2643                 :           0 :             endCt2--;
    2644                 :             :         }
    2645                 :          73 :         lenNumH1 = Ct1->lenNumH;
    2646                 :          73 :         lenNumH2 = Ct2->lenNumH;
    2647                 :             :         /* djb-rwth: removing redundant code */
    2648                 :             : 
    2649                 :          73 :         len_iso_sort_key1 = Ct1->len_iso_sort_key;
    2650                 :          73 :         len_iso_sort_key2 = Ct2->len_iso_sort_key;
    2651                 :             :         /* djb-rwth: removing redundant code */
    2652                 :             :     }
    2653                 :             : 
    2654         [ -  + ]:          94 :     if ((diff = -( endCt1 - endCt2 ))) /* djb-rwth: addressing LLVM warning */
    2655                 :             :     {
    2656                 :             :         /* negative sign reproduces results for NSC=28393 */
    2657                 :           0 :         goto done;
    2658                 :             :     }
    2659                 :             : 
    2660         [ +  + ]:          94 :     if (bSplitTautCompare)
    2661                 :             :     {
    2662                 :          42 :         midCt = inchi_min( Ct1->nLenCTAtOnly, Ct2->nLenCTAtOnly );
    2663         [ +  + ]:          42 :         if (midCt > endCt1)
    2664                 :             :         {
    2665                 :          21 :             midCt = endCt1;
    2666                 :             :         }
    2667                 :          42 :         midAt = inchi_min( maxVert, endAt1 ); /* djb-rwth: ignoring LLVM warning: variable used? */
    2668                 :             :     }
    2669                 :             :     else
    2670                 :             :     {
    2671                 :          52 :         midCt = endCt1;
    2672                 :          52 :         midAt = endAt1; /* djb-rwth: ignoring LLVM warning: variable used? */
    2673                 :             :     }
    2674                 :             : 
    2675                 :             : 
    2676                 :             :     /*************************************************************************/
    2677                 :             :     /************ layer 0: connection table without tautomeric groups ********/
    2678                 :             :     /*************************************************************************/
    2679   [ +  +  +  - ]:        1356 :     for (i = startCt1; i < midCt && Ct1->Ctbl[i] == Ct2->Ctbl[i]; i++)
    2680                 :             :     {
    2681                 :             :         ;
    2682                 :             :     }
    2683         [ -  + ]:          94 :     if (i < midCt)
    2684                 :             :     {
    2685                 :           0 :         diff = (int) Ct1->Ctbl[i] - (int) Ct2->Ctbl[i];
    2686                 :           0 :         goto done;
    2687                 :             :     }
    2688                 :             : 
    2689                 :             : 
    2690                 :             :     /*************************************************************************/
    2691                 :             :     /************* layer 1: H atoms without tautomeric H *********************/
    2692                 :             :     /*************************************************************************/
    2693                 :          94 :     nLayer++;
    2694   [ +  +  +  - ]:          94 :     if (Ct1->NumH && Ct2->NumH)
    2695                 :             :     {
    2696         [ -  + ]:          42 :         if ((diff = -( lenNumH1 - lenNumH2 ))) /* djb-rwth: addressing LLVM warning */
    2697                 :             :         {
    2698                 :             :             /* negative sign reproduces results for NSC=28393 */
    2699                 :           0 :             goto done;
    2700                 :             :         }
    2701         [ -  + ]:          42 :         if (endAt1 < maxVert)
    2702                 :             :         {
    2703                 :           0 :             midNumH = lenNumH1 = endAt1;
    2704                 :             :         }
    2705         [ +  - ]:          42 :         else if (bSplitTautCompare)
    2706                 :             :         {
    2707                 :          42 :             midNumH = maxVert;
    2708                 :             :         }
    2709                 :             :         else
    2710                 :             :         {
    2711                 :           0 :             midNumH = lenNumH1;
    2712                 :             :         }
    2713                 :             : 
    2714   [ +  +  +  - ]:         293 :         for (i = startAt1; i < midNumH && Ct1->NumH[i] == Ct2->NumH[i]; i++)
    2715                 :             :         {
    2716                 :             :             ;
    2717                 :             :         }
    2718         [ -  + ]:          42 :         if (i < midNumH)
    2719                 :             :         {
    2720                 :           0 :             diff = (int) Ct1->NumH[i] - (int) Ct2->NumH[i];
    2721                 :           0 :             goto done;
    2722                 :             :         }
    2723                 :             :     }
    2724                 :             : 
    2725                 :             : 
    2726                 :             :     /*************************************************************************/
    2727                 :             :     /************** layer 2: tautomeric part of CT and tautomeric H **********/
    2728                 :             :     /*************************************************************************/
    2729                 :          94 :     nLayer++;
    2730   [ +  +  +  - ]:         238 :     for (i = midCt; i < endCt1 && Ct1->Ctbl[i] == Ct2->Ctbl[i]; i++)
    2731                 :             :     {
    2732                 :             :         ; /* compare tautomeric groups part of CT */
    2733                 :             :     }
    2734         [ -  + ]:          94 :     if (i < endCt1)
    2735                 :             :     {
    2736                 :           0 :         diff = (int) Ct1->Ctbl[i] - (int) Ct2->Ctbl[i];
    2737                 :           0 :         goto done;
    2738                 :             :     }
    2739   [ +  +  +  - ]:          94 :     if (Ct1->NumH && Ct2->NumH)
    2740                 :             :     {
    2741   [ +  +  +  - ]:         130 :         for (i = midNumH; i < lenNumH1 && Ct1->NumH[i] == Ct2->NumH[i]; i++)
    2742                 :             :         {
    2743                 :             :             ; /* compare tautomeric H */
    2744                 :             :         }
    2745         [ -  + ]:          42 :         if (i < lenNumH1)
    2746                 :             :         {
    2747                 :           0 :             diff = (int) Ct1->NumH[i] - (int) Ct2->NumH[i];
    2748                 :           0 :             goto done;
    2749                 :             :         }
    2750                 :             :     }
    2751                 :             : 
    2752                 :             :     /*************************************************************************/
    2753                 :             :     /************** layer 3: Fixed H atoms ***********************************/
    2754                 :             :     /*************************************************************************/
    2755                 :          94 :     nLayer++;
    2756   [ -  +  -  - ]:          94 :     if (Ct1->NumHfixed && Ct2->NumHfixed)
    2757                 :             :     {
    2758   [ #  #  #  # ]:           0 :         for (i = startAt1; i < endAt1 && Ct1->NumHfixed[i] == Ct2->NumHfixed[i]; i++)
    2759                 :             :         {
    2760                 :             :             ;
    2761                 :             :         }
    2762         [ #  # ]:           0 :         if (i < endAt1)
    2763                 :             :         {
    2764                 :           0 :             diff = (int) Ct1->NumHfixed[i] - (int) Ct2->NumHfixed[i];
    2765                 :           0 :             goto done;
    2766                 :             :         }
    2767                 :             :     }
    2768                 :             : 
    2769                 :             : 
    2770                 :             :     /*************************************************************************/
    2771                 :             :     /************** layer 4: isotopic atoms, H and isotopic taut H ***********/
    2772                 :             :     /*************************************************************************/
    2773                 :          94 :     nLayer++;
    2774   [ +  -  -  - ]:          94 :     if (Ct1->iso_sort_key && Ct2->iso_sort_key)
    2775                 :             :     {
    2776         [ #  # ]:           0 :         if ((diff = -( len_iso_sort_key1 - len_iso_sort_key2 ))) /* djb-rwth: addressing LLVM warning */
    2777                 :             :         {
    2778                 :             :             /* negative sign reproduces results for NSC=28393 */
    2779                 :           0 :             goto done;
    2780                 :             :         }
    2781   [ #  #  #  # ]:           0 :         for (i = startAt1; i < endAt1 && Ct1->iso_sort_key[i] == Ct2->iso_sort_key[i]; i++)
    2782                 :             :         {
    2783                 :             :             ;
    2784                 :             :         }
    2785         [ #  # ]:           0 :         if (i < endAt1)
    2786                 :             :         {
    2787         [ #  # ]:           0 :             diff = Ct1->iso_sort_key[i] > Ct2->iso_sort_key[i] ? 1 : -1;
    2788                 :           0 :             goto done;
    2789                 :             :         }
    2790                 :             :     }
    2791                 :             : 
    2792                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    2793                 :             : 
    2794                 :             : 
    2795                 :             :     /*************************************************************************/
    2796                 :             :     /************** layer 6: Fixed isotopic H atoms **************************/
    2797                 :             :     /*************************************************************************/
    2798                 :             :     nLayer++;
    2799                 :             :     if (Ct1->iso_sort_key_Hfixed && Ct2->iso_sort_key_Hfixed)
    2800                 :             :     {
    2801                 :             :         for (i = startAt1; i < midAt && Ct1->iso_sort_key_Hfixed[i] == Ct2->iso_sort_key_Hfixed[i]; i++)
    2802                 :             :             ;
    2803                 :             :         if (i < midAt)
    2804                 :             :         {
    2805                 :             :             diff = Ct1->iso_sort_key_Hfixed[i] > Ct2->iso_sort_key_Hfixed[i] ? 1 : -1;
    2806                 :             :             goto done;
    2807                 :             :         }
    2808                 :             :     }
    2809                 :             : #endif
    2810                 :             : 
    2811                 :             : 
    2812                 :          94 : done:
    2813                 :             : 
    2814                 :             : #ifdef INCHI_CANON_MIN
    2815                 :          94 :     diff = -diff;
    2816                 :             : #endif
    2817                 :             : 
    2818         [ -  + ]:          94 :     if (diff)
    2819                 :             :     {
    2820         [ #  # ]:           0 :         diff = ( diff > 0 ) ? ( nLayer + 1 ) : -( nLayer + 1 ); /* return the discovered difference layer number >= 1 */
    2821                 :             :     }
    2822                 :             : 
    2823                 :          94 :     return diff;
    2824                 :             : }
    2825                 :             : 
    2826                 :             : 
    2827                 :             : /****************************************************************************/
    2828                 :           0 : int CtFullCompareLayers( kLeast *kLeastForLayer )
    2829                 :             : {
    2830                 :             :     int iLayer;
    2831                 :             :     /* check for the rejection condition: Lambda > zb_rho_fix */
    2832         [ #  # ]:           0 :     for (iLayer = 0; iLayer < MAX_LAYERS; iLayer++)
    2833                 :             :     {
    2834         [ #  # ]:           0 :         if (kLeastForLayer[iLayer].k)
    2835                 :             :         {
    2836         [ #  # ]:           0 :             return ( kLeastForLayer[iLayer].k > 0 ) ? ( iLayer + 1 ) : -( iLayer + 1 );
    2837                 :             :         }
    2838                 :             :     }
    2839                 :             : 
    2840                 :           0 :     return 0;
    2841                 :             : }
    2842                 :             : 
    2843                 :             : 
    2844                 :             : /****************************************************************************/
    2845                 :         204 : int CtCompareLayersGetFirstDiff( kLeast *kLeast_rho,
    2846                 :             :                                  int nOneAdditionalLayer,
    2847                 :             :                                  int *L_rho,
    2848                 :             :                                  int *I_rho,
    2849                 :             :                                  int *k_rho )
    2850                 :             : {
    2851                 :             :     int iLayer;
    2852         [ +  - ]:         204 :     if (kLeast_rho)
    2853                 :             :     {
    2854         [ +  + ]:       20604 :         for (iLayer = 0; iLayer < MAX_LAYERS; iLayer++)
    2855                 :             :         {
    2856         [ -  + ]:       20400 :             if (kLeast_rho[iLayer].k)
    2857                 :             :             {
    2858                 :           0 :                 *L_rho = iLayer;
    2859                 :           0 :                 *I_rho = kLeast_rho[iLayer].i;
    2860                 :           0 :                 *k_rho = kLeast_rho[iLayer].k;
    2861                 :           0 :                 break;
    2862                 :             :             }
    2863                 :             :         }
    2864         [ +  - ]:         204 :         if (iLayer == MAX_LAYERS)
    2865                 :             :         {
    2866         [ +  + ]:         204 :             if (nOneAdditionalLayer)
    2867                 :             :             {
    2868                 :          57 :                 *L_rho = nOneAdditionalLayer;  /* ??? subtract 1 ??? */
    2869                 :          57 :                 *I_rho = -1;
    2870                 :          57 :                 *k_rho = 0;
    2871                 :          57 :                 return 0; /* difference may be in the first additional layer */
    2872                 :             :             }
    2873                 :             :             else
    2874                 :             :             {
    2875                 :         147 :                 *L_rho = INCHI_CANON_INFINITY;
    2876                 :         147 :                 *I_rho = -1;
    2877                 :         147 :                 *k_rho = 0;
    2878                 :         147 :                 return 0; /* no difference found */
    2879                 :             :             }
    2880                 :             :         }
    2881                 :             :         else
    2882                 :             :         {
    2883                 :           0 :             return 1; /* difference in a real layer */
    2884                 :             :         }
    2885                 :             :     }
    2886                 :             :     else
    2887                 :             :     {
    2888                 :           0 :         return -1; /* no input, should not happen */
    2889                 :             :     }
    2890                 :             : }
    2891                 :             : 
    2892                 :             : 
    2893                 :             : /****************************************************************************/
    2894                 :         197 : int CtPartCompareLayers( kLeast *kLeast_rho,
    2895                 :             :                          int L_rho_fix_prev,
    2896                 :             :                          int nOneAdditionalLayer )
    2897                 :             : {
    2898                 :             :     int L_rho, I_rho, k_rho;
    2899         [ -  + ]:         197 :     if (0 < CtCompareLayersGetFirstDiff( kLeast_rho, nOneAdditionalLayer, &L_rho, &I_rho, &k_rho ) &&
    2900                 :             :          /* differences has been found in a real layer or all real layers are identical */
    2901         [ #  # ]:           0 :          L_rho <= L_rho_fix_prev)
    2902                 :             :     {
    2903                 :             :         /* in this layer pzb_rho == pzb_rho_fix or in the previous real layer */
    2904         [ #  # ]:           0 :         return k_rho > 0 ? ( L_rho + 1 ) : -( L_rho + 1 );
    2905                 :             :     }
    2906                 :             : 
    2907                 :         197 :     return 0;
    2908                 :             : }
    2909                 :             : 
    2910                 :             : 
    2911                 :             : /****************************************************************************/
    2912                 :          94 : void UpdateCompareLayers( kLeast kLeastForLayer[], int hzz )
    2913                 :             : {
    2914                 :             :     int i;
    2915         [ +  - ]:          94 :     if (kLeastForLayer)
    2916                 :             :     {
    2917         [ +  + ]:        9494 :         for (i = 0; i < MAX_LAYERS; i++)
    2918                 :             :         {
    2919         [ -  + ]:        9400 :             if (abs( kLeastForLayer[i].k ) >= hzz)
    2920                 :             :             {
    2921                 :           0 :                 kLeastForLayer[i].k = 0;
    2922                 :           0 :                 kLeastForLayer[i].i = 0;
    2923                 :             :             }
    2924                 :             :         }
    2925                 :             :     }
    2926                 :          94 : }
    2927                 :             : 
    2928                 :             : 
    2929                 :             : /****************************************************************************/
    2930                 :         331 : void CtPartCopy( ConTable *Ct1 /* to */,
    2931                 :             :                  ConTable *Ct2 /* from */,
    2932                 :             :                  int k )
    2933                 :             : {
    2934                 :             :     int     startCt1, startCt2, endCt2;
    2935                 :         331 :     int     len2, len2H, len2Hfixed = 0, len2iso_sort_key, len2iso_exchg_atnos, i;
    2936                 :             :     int     startAt1, startAt2, endAt2; /*endCt,*/
    2937                 :             : 
    2938                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    2939                 :             :     int     len2iso_sort_key_Hfixed;
    2940                 :             : #endif
    2941                 :             : 
    2942                 :         331 :     k--;
    2943                 :             : 
    2944         [ +  + ]:         331 :     if (k)
    2945                 :             :     {
    2946                 :         106 :         startCt1 = Ct1->nextCtblPos[k - 1];
    2947                 :         106 :         startCt2 = Ct2->nextCtblPos[k - 1];
    2948                 :         106 :         startAt1 = Ct1->nextAtRank[k - 1] - 1;
    2949                 :         106 :         startAt2 = Ct2->nextAtRank[k - 1] - 1;
    2950                 :             :     }
    2951                 :             :     else
    2952                 :             :     {
    2953                 :         225 :         startCt1 = startCt2 = 0;
    2954                 :         225 :         startAt1 = startAt2 = 0;
    2955                 :             :     }
    2956                 :             : 
    2957                 :             :     /* djb-rwth: removing redundant code */
    2958                 :         331 :     endCt2 = Ct2->nextCtblPos[k];
    2959                 :             :     /* djb-rwth: removing redundant code */
    2960                 :         331 :     endAt2 = (int) Ct2->nextAtRank[k] - 1;
    2961                 :             : 
    2962                 :         331 :     len2 = endCt2 - startCt2;
    2963                 :             :     /* len    = min(len1, len2); */
    2964                 :             : 
    2965                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    2966                 :             :     if (startCt1 != startCt2 || startAt1 != startAt2)
    2967                 :             :     {
    2968                 :             :         int stop = 1;
    2969                 :             :     }
    2970                 :             : #endif
    2971                 :             : 
    2972                 :             :     /* copy connection table: Ctbl */
    2973         [ +  + ]:        2940 :     for (i = 0; i < len2; i++)
    2974                 :             :     {
    2975                 :        2609 :         Ct1->Ctbl[startCt1 + i] = Ct2->Ctbl[startCt2 + i];
    2976                 :             :     }
    2977                 :             : 
    2978                 :             :     /* copy number of H: NumH */
    2979                 :         331 :     len2H = 0;
    2980   [ +  +  +  + ]:         331 :     if (Ct1->NumH && Ct2->NumH)
    2981                 :             :     {
    2982                 :          42 :         len2H = endAt2 - startAt2;
    2983         [ +  + ]:          42 :         if (endAt2 > Ct2->maxVert)
    2984                 :             :         {
    2985                 :          14 :             len2H = Ct2->lenNumH - startAt2;
    2986                 :             :         }
    2987         [ +  + ]:         178 :         for (i = 0; i < len2H; i++)
    2988                 :             :         {
    2989                 :         136 :             Ct1->NumH[startAt1 + i] = Ct2->NumH[startAt2 + i];
    2990                 :             :         }
    2991                 :             :     }
    2992                 :             : 
    2993                 :             :     /* copy number of fixed H */
    2994                 :             :     /* djb-rwth: removing redundant code */
    2995   [ -  +  -  - ]:         331 :     if (Ct1->NumHfixed && Ct2->NumHfixed)
    2996                 :             :     {
    2997                 :           0 :         len2Hfixed = endAt2 - startAt2;
    2998         [ #  # ]:           0 :         for (i = 0; i < len2Hfixed; i++)
    2999                 :             :         {
    3000                 :           0 :             Ct1->NumHfixed[startAt1 + i] = Ct2->NumHfixed[startAt2 + i];
    3001                 :             :         }
    3002                 :             :     }
    3003                 :             : 
    3004                 :             :     /* copy isotopic keys */
    3005                 :         331 :     len2iso_sort_key = 0;
    3006   [ -  +  -  - ]:         331 :     if (Ct1->iso_sort_key && Ct2->iso_sort_key)
    3007                 :             :     {
    3008                 :           0 :         len2iso_sort_key = endAt2 - startAt2;
    3009         [ #  # ]:           0 :         for (i = 0; i < len2iso_sort_key; i++)
    3010                 :             :         {
    3011                 :           0 :             Ct1->iso_sort_key[startAt1 + i] = Ct2->iso_sort_key[startAt2 + i];
    3012                 :             :         }
    3013                 :             :     }
    3014                 :             : 
    3015                 :         331 :     len2iso_exchg_atnos = 0;
    3016   [ -  +  -  - ]:         331 :     if (Ct1->iso_exchg_atnos && Ct2->iso_exchg_atnos)
    3017                 :             :     {
    3018                 :           0 :         len2iso_exchg_atnos = endAt2 - startAt2;
    3019         [ #  # ]:           0 :         for (i = 0; i < len2iso_exchg_atnos; i++)
    3020                 :             :         {
    3021                 :           0 :             Ct1->iso_exchg_atnos[startAt1 + i] = Ct2->iso_exchg_atnos[startAt2 + i];
    3022                 :             :         }
    3023                 :             :     }
    3024                 :             : 
    3025                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    3026                 :             :     len2iso_sort_key_Hfixed = 0;
    3027                 :             :     if (Ct1->iso_sort_key_Hfixed && Ct2->iso_sort_key_Hfixed)
    3028                 :             :     {
    3029                 :             :         len2iso_sort_key_Hfixed = endAt2 - startAt2;
    3030                 :             :         for (i = 0; i < len2iso_sort_key; i++)
    3031                 :             :         {
    3032                 :             :             Ct1->iso_sort_key_Hfixed[startAt1 + i] = Ct2->iso_sort_key_Hfixed[startAt2 + i];
    3033                 :             :         }
    3034                 :             :     }
    3035                 :             : #endif
    3036                 :             : 
    3037                 :         331 :     Ct1->lenCt = startCt1 + len2;
    3038                 :         331 :     Ct1->nextCtblPos[k] = startCt1 + len2;
    3039                 :         331 :     Ct1->nextAtRank[k] = Ct2->nextAtRank[k];
    3040         [ +  + ]:         331 :     if (len2H)
    3041                 :             :     {
    3042                 :          42 :         Ct1->lenNumH = startAt1 + len2H;
    3043                 :             :     }
    3044                 :             : 
    3045                 :             :     /*
    3046                 :             :     if ( len2Hfixed )
    3047                 :             :     {
    3048                 :             :         Ct1->lenNumHfixed   = startAt1 + len2Hfixed;
    3049                 :             :     }
    3050                 :             :     */
    3051                 :             : 
    3052         [ -  + ]:         331 :     if (len2iso_sort_key)
    3053                 :             :     {
    3054                 :           0 :         Ct1->len_iso_sort_key = startAt1 + len2iso_sort_key;
    3055                 :             :     }
    3056         [ -  + ]:         331 :     if (len2iso_exchg_atnos)
    3057                 :             :     {
    3058                 :           0 :         Ct1->len_iso_exchg_atnos = startAt1 + len2iso_exchg_atnos;
    3059                 :             :     }
    3060                 :             : 
    3061                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    3062                 :             :     if (len2iso_sort_key_Hfixed)
    3063                 :             :     {
    3064                 :             :         Ct1->len_iso_sort_key_Hfixed = startAt1 + len2iso_sort_key_Hfixed;
    3065                 :             :     }
    3066                 :             : #endif
    3067                 :             : 
    3068                 :             : #ifdef INCHI_CANON_USE_HASH
    3069                 :             :     Ct1->hash[k] = Ct2->hash[k];
    3070                 :             : #endif
    3071                 :             : 
    3072                 :         331 :     Ct1->lenPos = k + 1;
    3073                 :             :     INCHI_HEAPCHK
    3074                 :         331 : }
    3075                 :             : 
    3076                 :             : 
    3077                 :             : /****************************************************************************/
    3078                 :         161 : void CtFullCopy( ConTable *Ct1, ConTable *Ct2 )
    3079                 :             : {
    3080                 :             :     /* Ct1 does not have INCHI_CANON_INFINITY termination */
    3081                 :             :     int k;
    3082         [ +  + ]:         348 :     for (k = 0; k < Ct2->lenPos; k++)
    3083                 :             :     {
    3084                 :         187 :         CtPartCopy( Ct1 /* to */, Ct2 /* from */, k + 1 );
    3085                 :             :     }
    3086                 :         161 : }
    3087                 :             : 
    3088                 :             : 
    3089                 :             : /****************************************************************************/
    3090                 :          73 : void TranspositionGetMcrAndFixSetAndUnorderedPartition( CANON_GLOBALS *pCG,
    3091                 :             :                                                         Transposition *gamma,
    3092                 :             :                                                         NodeSet *McrSet,
    3093                 :             :                                                         NodeSet *FixSet,
    3094                 :             :                                                         int n,
    3095                 :             :                                                         int l,
    3096                 :             :                                                         UnorderedPartition *p )
    3097                 :             : {
    3098                 :             :     int i, j, k, mcr;
    3099                 :             :     AT_RANK next;
    3100                 :          73 :     bitWord *McrBits = McrSet->bitword[l - 1];
    3101                 :          73 :     bitWord *FixBits = FixSet->bitword[l - 1];
    3102                 :          73 :     int     len = McrSet->len_set * sizeof( bitWord );
    3103                 :             : 
    3104                 :          73 :     memset( McrBits, 0, len ); /* djb-rwth: memset_s C11/Annex K variant? */
    3105                 :          73 :     memset( FixBits, 0, len ); /* djb-rwth: memset_s C11/Annex K variant? */
    3106         [ +  + ]:         701 :     for (i = 0; i < n; i++)
    3107                 :             :     {
    3108                 :         628 :         p->equ2[i] = INCHI_CANON_INFINITY; /* for debug only */
    3109                 :             :     }
    3110                 :             : 
    3111         [ +  + ]:         701 :     for (i = 0; i < n; i++)
    3112                 :             :     {
    3113                 :         628 :         j = (int) ( next = gamma->nAtNumb[i] );
    3114                 :             : 
    3115         [ +  + ]:         628 :         if (j == i)
    3116                 :             :         {
    3117                 :         346 :             FixBits[i / pCG->m_num_bit] |= pCG->m_bBit[i % pCG->m_num_bit];
    3118                 :         346 :             McrBits[i / pCG->m_num_bit] |= pCG->m_bBit[i % pCG->m_num_bit];
    3119                 :             :             /* p->next[i] = INCHI_CANON_INFINITY; */ /* no link to same orbit points */
    3120                 :         346 :             p->equ2[i] = next;  /* fixed point */
    3121                 :             :         }
    3122         [ +  + ]:         282 :         else if (!( rank_mark_bit & next ))
    3123                 :             :         {
    3124                 :         141 :             gamma->nAtNumb[i] |= rank_mark_bit;
    3125                 :         141 :             mcr = inchi_min( j, i );
    3126                 :             :             /* djb-rwth: removing redundant code */
    3127                 :             :             /* mark all nodes in the cycle to ignore later; find mcr */
    3128         [ +  + ]:         282 :             while (!( rank_mark_bit & ( next = gamma->nAtNumb[j] ) ))
    3129                 :             :             {
    3130                 :         141 :                 gamma->nAtNumb[j] |= rank_mark_bit;
    3131                 :         141 :                 j = (int) next;
    3132         [ -  + ]:         141 :                 if (mcr > j)
    3133                 :             :                 {
    3134                 :           0 :                     mcr = j;
    3135                 :             :                 }
    3136                 :             :                 /* djb-rwth: removing redundant code */
    3137                 :             :             }
    3138                 :         141 :             McrBits[mcr / pCG->m_num_bit] |= pCG->m_bBit[mcr % pCG->m_num_bit]; /* save mcr */
    3139                 :             :             /* fill out the unordered partition, the mcr first, other in the cycle after that */
    3140                 :         141 :             p->equ2[mcr] = mcr;
    3141         [ +  + ]:         282 :             for (k = mcr; mcr != ( j = (int) ( rank_mask_bit & gamma->nAtNumb[k] ) ); k = j)
    3142                 :             :             {
    3143                 :         141 :                 p->equ2[j] = mcr;
    3144                 :             :             }
    3145                 :             :         }
    3146                 :             :     }
    3147                 :             : 
    3148                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    3149                 :             :     /* for debug only */
    3150                 :             :     for (i = 0; i < n; i++)
    3151                 :             :     {
    3152                 :             :         if (p->equ2[i] >= n)
    3153                 :             :         {
    3154                 :             :             int stop = 1;
    3155                 :             :         }
    3156                 :             :     }
    3157                 :             : #endif
    3158                 :             : 
    3159                 :             :     /* remove the marks */
    3160         [ +  + ]:         701 :     for (i = 0; i < n; i++)
    3161                 :             :     {
    3162                 :         628 :         gamma->nAtNumb[i] &= rank_mask_bit;
    3163                 :             :     }
    3164                 :             : 
    3165                 :             :     INCHI_HEAPCHK
    3166                 :          73 : }
    3167                 :             : 
    3168                 :             : 
    3169                 :             : /****************************************************************************/
    3170                 :         175 : int SetBitCreate( CANON_GLOBALS *pCG )
    3171                 :             : {
    3172                 :         175 :     bitWord b1 = 1, b2;
    3173                 :             :     AT_NUMB n1, n2;
    3174                 :             : #ifdef INCHI_CANON_USE_HASH
    3175                 :             :     CtHash  h1, h2;
    3176                 :             : #endif
    3177                 :             :     int    i;
    3178                 :             : 
    3179         [ +  + ]:         175 :     if (pCG->m_bBitInitialized)
    3180                 :             :     {
    3181                 :             :         INCHI_HEAPCHK
    3182                 :          54 :         return 0; /* already created */
    3183                 :             :     }
    3184                 :             : 
    3185                 :             :     /* djb-rwth: removing redundant code */
    3186                 :         121 :     pCG->m_num_bit = 1;
    3187         [ +  + ]:        1936 :     for (b1 = 1, pCG->m_num_bit = 1; b1 < ( b2 = (bitWord) ( ( b1 << 1 )& BIT_WORD_MASK ) ); b1 = b2, pCG->m_num_bit++)
    3188                 :             :     {
    3189                 :             :         ;
    3190                 :             :     }
    3191                 :         121 :     pCG->m_bBit = (bitWord*) inchi_calloc( pCG->m_num_bit, sizeof( bitWord ) );
    3192         [ -  + ]:         121 :     if (!pCG->m_bBit)
    3193                 :             :     {
    3194                 :             :         INCHI_HEAPCHK
    3195                 :           0 :             return -1; /* failed */
    3196                 :             :     }
    3197         [ +  + ]:        2057 :     for (i = 0, b1 = 1; i < pCG->m_num_bit; i++, b1 <<= 1)
    3198                 :             :     {
    3199                 :        1936 :         pCG->m_bBit[i] = b1;
    3200                 :             :     }
    3201                 :             : 
    3202         [ +  + ]:        1936 :     for (n1 = 1; n1 < ( n2 = (AT_RANK) ( ( n1 << 1 )& AT_RANK_MASK ) ); n1 = n2)
    3203                 :             :     {
    3204                 :             :         ;
    3205                 :             :     }
    3206                 :         121 :     rank_mark_bit = n1;
    3207                 :         121 :     rank_mask_bit = ~n1;
    3208                 :             : 
    3209                 :             : #ifdef INCHI_CANON_USE_HASH
    3210                 :             :     for (h1 = 1; h1 < ( h2 = ( h1 << 1 ) ); h1 = h2)
    3211                 :             :     {
    3212                 :             :         ;
    3213                 :             :     }
    3214                 :             :     hash_mark_bit = h1;
    3215                 :             : #endif
    3216                 :         121 :     pCG->m_bBitInitialized = 1;
    3217                 :             :     INCHI_HEAPCHK
    3218                 :             : 
    3219                 :         121 :     return 1;
    3220                 :             : }
    3221                 :             : 
    3222                 :             : 
    3223                 :             : /****************************************************************************/
    3224                 :         123 : int SetBitFree( CANON_GLOBALS *pCG )
    3225                 :             : {
    3226         [ +  + ]:         123 :     if (pCG->m_bBit)
    3227                 :             :     {
    3228         [ +  - ]:         121 :         inchi_free( pCG->m_bBit );
    3229                 :         121 :         pCG->m_bBit = NULL;
    3230                 :             :         INCHI_HEAPCHK
    3231                 :         121 :         return 1; /* success */
    3232                 :             :     }
    3233                 :             : 
    3234                 :             :     INCHI_HEAPCHK
    3235                 :             : 
    3236                 :           2 :     return 0; /* already destroyed */
    3237                 :             : }
    3238                 :             : 
    3239                 :             : 
    3240                 :             : 
    3241                 :             : #ifdef NEVER  /* { how to renumber a graph */
    3242                 :             : /****************************************************************************/
    3243                 :             : void RenumberTheGraph( int n,
    3244                 :             :                        NEIGH_LIST *NeighList,
    3245                 :             :                        AT_NUMB *old2new,
    3246                 :             :                        AT_NUMB *new2old,
    3247                 :             :                        S_CHAR *mark,
    3248                 :             :                        int bDone )
    3249                 :             : {
    3250                 :             :     int        i, k, j;
    3251                 :             :     NEIGH_LIST nl;
    3252                 :             : 
    3253                 :             :     /* renumber neighbors */
    3254                 :             :     for (i = 0; i < n; i++)
    3255                 :             :     {
    3256                 :             :         for (j = 1; j <= NeighList[i][0]; j++)
    3257                 :             :         {
    3258                 :             :             NeighList[i][j] = old2new[NeighList[i][j]];
    3259                 :             :         }
    3260                 :             :     }
    3261                 :             : 
    3262                 :             :     /* rearrange NeighList in situ using new2old[] */
    3263                 :             :     for (k = 0; k < n; k++)
    3264                 :             :     {
    3265                 :             :         if (mark[k] & bDone)
    3266                 :             :             continue;
    3267                 :             :         if (k == ( j = new2old[k] ))
    3268                 :             :         {
    3269                 :             :             mark[k] |= bDone;
    3270                 :             :             continue;
    3271                 :             :         }
    3272                 :             :         /* transposition cycle */
    3273                 :             :         i = k;
    3274                 :             :         nl = NeighList[k];
    3275                 :             :         do
    3276                 :             :         {
    3277                 :             :             NeighList[i] = NeighList[j];
    3278                 :             :             mark[i] |= bDone;
    3279                 :             :             i = j;
    3280                 :             :         }
    3281                 :             :         while (k != ( j = new2old[i] ));
    3282                 :             :         NeighList[i] = nl;
    3283                 :             :         mark[i] |= bDone;
    3284                 :             :     }
    3285                 :             : 
    3286                 :             : #ifdef NEVER
    3287                 :             :     /* rearrange NeighList in situ using old2new[] */
    3288                 :             :     s = 0;
    3289                 :             :     for (k = 0; k < n; k++)
    3290                 :             :     {
    3291                 :             :         if (mark[k] & bDone)
    3292                 :             :             continue;
    3293                 :             :         if (k == ( j = old2new[k] ))
    3294                 :             :         {
    3295                 :             :             mark[k] |= bDone;
    3296                 :             :             continue;
    3297                 :             :         }
    3298                 :             :         /* transposition cycle */
    3299                 :             :         i = k;
    3300                 :             :         /* NeighList[j] goes to ith position */
    3301                 :             :         nl2[s] = NeighList[j];
    3302                 :             :         s ^= 1;
    3303                 :             :         do
    3304                 :             :         {
    3305                 :             :             nl2[s] = NeighList[i];
    3306                 :             :             NeighList[i] = nl2[s ^= 1];
    3307                 :             :             mark[i] |= bDone;
    3308                 :             :             i = j;
    3309                 :             :             j = old2new[i];
    3310                 :             :         }
    3311                 :             :         while (k != ( j = old2new[i] ));
    3312                 :             :         NeighList[j] = nl2[s ^= 1];
    3313                 :             :         mark[j] |= bDone;
    3314                 :             :     }
    3315                 :             : #endif
    3316                 :             : 
    3317                 :             : }
    3318                 :             : 
    3319                 :             : 
    3320                 :             : /****************************************************************************/
    3321                 :             : void RearrangeAtRankArray( int n,
    3322                 :             :                            AT_RANK *nRank,
    3323                 :             :                            AT_NUMB *new2old,
    3324                 :             :                            S_CHAR *mark,
    3325                 :             :                            int bDone )
    3326                 :             : {
    3327                 :             :     int i, k, j;
    3328                 :             :     AT_RANK r;
    3329                 :             :     /* rearrange the array in situ using new2old[] */
    3330                 :             :     for (k = 0; k < n; k++)
    3331                 :             :     {
    3332                 :             :         if (mark[k] & bDone)
    3333                 :             :         {
    3334                 :             :             continue;
    3335                 :             :         }
    3336                 :             :         if (k == ( j = new2old[k] ))
    3337                 :             :         {
    3338                 :             :             mark[k] |= bDone;
    3339                 :             :             continue;
    3340                 :             :         }
    3341                 :             :         /* transposition cycle */
    3342                 :             :         i = k;
    3343                 :             :         r = nRank[k];
    3344                 :             :         do
    3345                 :             :         {
    3346                 :             :             nRank[i] = nRank[j];
    3347                 :             :             mark[i] |= bDone;
    3348                 :             :             i = j;
    3349                 :             :         }
    3350                 :             :         while (k != ( j = new2old[i] ));
    3351                 :             :         nRank[i] = r;
    3352                 :             :         mark[i] |= bDone;
    3353                 :             :     }
    3354                 :             : 
    3355                 :             : }
    3356                 :             : 
    3357                 :             : 
    3358                 :             : /****************************************************************************/
    3359                 :             : void RenumberAtNumbArray( int n, AT_NUMB *nAtNumb, AT_NUMB *old2new )
    3360                 :             : {
    3361                 :             :     int i;
    3362                 :             :     for (i = 0; i < n; i++)
    3363                 :             :     {
    3364                 :             :         nAtNumb[i] = old2new[nAtNumb[i]];
    3365                 :             :     }
    3366                 :             : }
    3367                 :             : 
    3368                 :             : 
    3369                 :             : /****************************************************************************/
    3370                 :             : int  GetCanonRanking2( int num_atoms,
    3371                 :             :                        int num_at_tg,
    3372                 :             :                        int num_max,
    3373                 :             :                        int bDigraph,
    3374                 :             :                        sp_ATOM* at,
    3375                 :             :                        AT_RANK **pRankStack,
    3376                 :             :                        int nNumPrevRanks,
    3377                 :             :                        AT_RANK *nSymmRank,
    3378                 :             :                        AT_RANK *nCanonRank,
    3379                 :             :                        NEIGH_LIST *NeighList,
    3380                 :             :                        AT_RANK *nTempRank,
    3381                 :             :                        CANON_STAT* pCS )
    3382                 :             : {
    3383                 :             :     void *pzb_rho = NULL;
    3384                 :             :     int ret, cmp1 = 0, cmp2 = 0;
    3385                 :             : 
    3386                 :             :     int i, j, k, n;
    3387                 :             :     AT_NUMB *old2new = NULL, *new2old = NULL, m, r1, r2;
    3388                 :             :     S_CHAR  *mark = NULL;
    3389                 :             : 
    3390                 :             :     int      nMaxLenCt = pCS->nMaxLenLinearCT;
    3391                 :             :     AT_RANK *pCt = pCS->LinearCT;
    3392                 :             :     int      nLenCt = pCS->nLenLinearCT;
    3393                 :             :     AT_RANK *pCt0 = pCS->LinearCT;
    3394                 :             :     int      nLenCt0 = pCS->nLenLinearCT;
    3395                 :             : 
    3396                 :             : 
    3397                 :             :     CANON_DATA CanonData;
    3398                 :             :     CANON_DATA *pCD = &CanonData;
    3399                 :             :     CANON_COUNTS CanonCounts;
    3400                 :             :     CANON_COUNTS *pCC = &CanonCounts;
    3401                 :             :     memset( pCD, 0, sizeof( pCD[0] ) );
    3402                 :             :     memset( pCC, 0, sizeof( pCC[0] ) );
    3403                 :             :     /* pointers */
    3404                 :             :     pCD->LinearCT = pCS->LinearCT;
    3405                 :             :     /* variables - unchanged */
    3406                 :             :     pCD->ulTimeOutTime = pCS->ulTimeOutTime;
    3407                 :             :     pCD->nMaxLenLinearCT = pCS->nMaxLenLinearCT;
    3408                 :             :     /* return values & input/output */
    3409                 :             :     pCD->nLenLinearCT = pCS->nLenLinearCT;
    3410                 :             : 
    3411                 :             :     pCC->lNumBreakTies = pCS->lNumBreakTies;
    3412                 :             :     pCC->lNumDecreasedCT = pCS->lNumDecreasedCT;
    3413                 :             :     pCC->lNumRejectedCT = pCS->lNumRejectedCT;
    3414                 :             :     pCC->lNumEqualCT = pCS->lNumEqualCT;
    3415                 :             :     pCC->lNumTotCT = pCS->lNumTotCT;
    3416                 :             : 
    3417                 :             :     ret = CanonGraph( ic, pCG, num_atoms, num_at_tg, num_max, bDigraph,
    3418                 :             :                       NeighList, (Partition *) pRankStack, nSymmRank,
    3419                 :             :                       nCanonRank, pCS->nPrevAtomNumber, pCD, pCC, NULL,
    3420                 :             :                       &pzb_rho, LargeMolecules );
    3421                 :             : 
    3422                 :             :     pCS->nLenLinearCT = pCD->nLenLinearCT;
    3423                 :             :     pCS->lNumBreakTies = pCC->lNumBreakTies;
    3424                 :             :     pCS->lNumDecreasedCT = pCC->lNumDecreasedCT;
    3425                 :             :     pCS->lNumRejectedCT = pCC->lNumRejectedCT;
    3426                 :             :     pCS->lNumEqualCT = pCC->lNumEqualCT;
    3427                 :             :     pCS->lNumTotCT = pCC->lNumTotCT;
    3428                 :             : 
    3429                 :             : 
    3430                 :             :     /* save the connection table for comparison with the 2nd one */
    3431                 :             :     pCt0 = (AT_RANK*) inchi_calloc( nMaxLenCt, sizeof( pCt0[0] ) );
    3432                 :             :     memcpy( pCt0, pCS->LinearCT, nMaxLenCt * sizeof( pCt0[0] ) );
    3433                 :             :     nLenCt0 = pCS->nLenLinearCT;
    3434                 :             : 
    3435                 :             :     /**********************************************************/
    3436                 :             :     /* rearrange numbering to make canon. numbering the first */
    3437                 :             :     /**********************************************************/
    3438                 :             :     n = num_at_tg;
    3439                 :             :     /* 1. get transpositions */
    3440                 :             :     old2new = (AT_NUMB*) inchi_calloc( n, sizeof( old2new[0] ) );
    3441                 :             :     new2old = (AT_NUMB*) inchi_calloc( n, sizeof( new2old[0] ) );
    3442                 :             :     mark = (S_CHAR *) inchi_calloc( n, sizeof( mark[0] ) );
    3443                 :             :     for (i = 0; i < n; i++)
    3444                 :             :     {
    3445                 :             :         /* forward transposition: at[i] -> at[old2new[i]] position */
    3446                 :             :         old2new[i] = m = nCanonRank[i] - 1;
    3447                 :             :         /* forward transposition: at[new2old[i]] -> at[i] position */
    3448                 :             :         new2old[m] = i;
    3449                 :             :     }
    3450                 :             :     /* rearrange input data according to the new numbering */
    3451                 :             :     RenumberTheGraph( n, NeighList, old2new, new2old, mark, 1 );
    3452                 :             :     RearrangeAtRankArray( n, pRankStack[0], new2old, mark, 2 );
    3453                 :             :     RenumberAtNumbArray( n, pRankStack[1], old2new );
    3454                 :             :     /* make sure the atom numbers are sorted */
    3455                 :             :     for (i = k = 0, r1 = pRankStack[0][pRankStack[1][i]]; i < n; r1 = r2)
    3456                 :             :     {
    3457                 :             :         for (j = i++; i < n && r1 == ( r2 = pRankStack[0][pRankStack[1][i]] ); i++)
    3458                 :             :         {
    3459                 :             :             ;
    3460                 :             :         }
    3461                 :             :         if (i - j > 1)
    3462                 :             :         {
    3463                 :             :             k += insertions_sort_AT_RANK( pRankStack[1] + j, i - j );
    3464                 :             :         }
    3465                 :             :     }
    3466                 :             : 
    3467                 :             :     ret = CanonGraph( ic, pCG, num_atoms, num_at_tg, num_max,
    3468                 :             :                       bDigraph, NeighList, (Partition *) pRankStack,
    3469                 :             :                       nSymmRank, nCanonRank,
    3470                 :             :                       NULL, LargeMolecules );
    3471                 :             : 
    3472                 :             :     pCS->nLenLinearCT = pCD->nLenLinearCT;
    3473                 :             :     pCS->lNumBreakTies = pCC->lNumBreakTies;
    3474                 :             :     pCS->lNumDecreasedCT = pCC->lNumDecreasedCT;
    3475                 :             :     pCS->lNumRejectedCT = pCC->lNumRejectedCT;
    3476                 :             :     pCS->lNumEqualCT = pCC->lNumEqualCT;
    3477                 :             :     pCS->lNumTotCT = pCC->lNumTotCT;
    3478                 :             : 
    3479                 :             : 
    3480                 :             :     /* compare the connection tables */
    3481                 :             :     cmp1 = nLenCt0 - pCS->nLenLinearCT;
    3482                 :             :     cmp2 = memcmp( pCt0, pCS->LinearCT, pCS->nLenLinearCT * sizeof( pCt0[0] ) );
    3483                 :             : 
    3484                 :             : #ifdef _DEBUG
    3485                 :             :     if (cmp1 || cmp2)
    3486                 :             :     {
    3487                 :             :         int stop = 1;
    3488                 :             :     }
    3489                 :             : #endif
    3490                 :             : 
    3491                 :             :     /**********************************************************/
    3492                 :             :     /* rearrange numbering back to the original numbering     */
    3493                 :             :     /**********************************************************/
    3494                 :             : 
    3495                 :             :     /* restore the input data to its original numbering */
    3496                 :             : 
    3497                 :             :     RenumberTheGraph( n, NeighList, new2old, old2new, mark, 4 );
    3498                 :             : 
    3499                 :             :     RearrangeAtRankArray( n, pRankStack[0], old2new, mark, 8 );
    3500                 :             : 
    3501                 :             :     RenumberAtNumbArray( n, pRankStack[1], new2old );
    3502                 :             : 
    3503                 :             :     /* rearrange the output data to the original numbering */
    3504                 :             : 
    3505                 :             :     RearrangeAtRankArray( n, nCanonRank, old2new, mark, 16 );
    3506                 :             :     RenumberAtNumbArray( n, pCS->nPrevAtomNumber, new2old );
    3507                 :             :     RearrangeAtRankArray( n, nSymmRank, old2new, mark, 32 );
    3508                 :             : 
    3509                 :             :     /* free memory */
    3510                 :             :     CTableFree( pzb_rho );
    3511                 :             :     if (pzb_rho)
    3512                 :             :     {
    3513                 :             :         inchi_free( pzb_rho );
    3514                 :             :     }
    3515                 :             : 
    3516                 :             :     inchi_free( old2new );
    3517                 :             :     inchi_free( new2old );
    3518                 :             :     inchi_free( mark );
    3519                 :             :     inchi_free( pCt0 );
    3520                 :             : 
    3521                 :             :     return ret;
    3522                 :             : }
    3523                 :             : 
    3524                 :             : #endif  /* } */
    3525                 :             : 
    3526                 :             : 
    3527                 :             : #define QZFIX_OK(X) ((X)<=0)
    3528                 :             : 
    3529                 :             : 
    3530                 :             : /****************************************************************************/
    3531                 :         175 : int GetOneAdditionalLayer( CANON_DATA *pCD, ConTable *pzb_rho_fix )
    3532                 :             : {
    3533                 :         175 :     int nLastLayer = -1, nNumLast = 0, nLayer = 0;
    3534                 :             : 
    3535   [ +  -  +  + ]:         175 :     if (!pCD || !pzb_rho_fix)
    3536                 :             :     {
    3537                 :         161 :         return 0;
    3538                 :             :     }
    3539                 :             : 
    3540                 :          14 :     nLayer++; /* 1 */
    3541   [ +  -  -  + ]:          14 :     if (pCD->NumH && !pzb_rho_fix->NumH)
    3542                 :             :     {
    3543                 :           0 :         nLastLayer = nLayer;
    3544                 :           0 :         nNumLast++;
    3545                 :             :     }
    3546                 :             : 
    3547                 :          14 :     nLayer++; /* 2 */
    3548   [ +  +  +  - ]:          14 :     if (pCD->nLenCTAtOnly < pCD->nLenLinearCT && pzb_rho_fix->nLenCTAtOnly == pzb_rho_fix->lenCt)
    3549                 :             :     {
    3550                 :           7 :         nLastLayer = nLayer;
    3551                 :           7 :         nNumLast++;
    3552                 :             :     }
    3553                 :             : 
    3554                 :          14 :     nLayer++; /* 3 */
    3555   [ -  +  -  - ]:          14 :     if (pCD->NumHfixed && !pzb_rho_fix->NumHfixed)
    3556                 :             :     {
    3557                 :           0 :         nLastLayer = nLayer;
    3558                 :           0 :         nNumLast++;
    3559                 :             :     }
    3560                 :             : 
    3561                 :          14 :     nLayer++; /* 4 */
    3562   [ -  +  -  - ]:          14 :     if (pCD->iso_sort_key && !pzb_rho_fix->iso_sort_key)
    3563                 :             :     {
    3564                 :           0 :         nLastLayer = nLayer;
    3565                 :           0 :         nNumLast++;
    3566                 :             :     }
    3567                 :             : 
    3568                 :             :     /*
    3569                 :             :     nLayer ++; // 5
    3570                 :             :     if ( pCD->nLenCTAtOnly < pCD->nLenLinearCT && pCD->iso_sort_key &&
    3571                 :             :         (pzb_rho_fix->nLenCTAtOnly == pzb_rho_fix->lenCt || !pzb_rho_fix->iso_sort_key ) )
    3572                 :             :         {
    3573                 :             :         nLastLayer = nLayer;
    3574                 :             :         nNumLast ++;
    3575                 :             :     }
    3576                 :             :     */
    3577                 :             : 
    3578                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    3579                 :             : 
    3580                 :             :     nLayer++; /* 6 */
    3581                 :             :     if (pCD->iso_sort_key_Hfixed && !pzb_rho_fix->iso_sort_key_Hfixed)
    3582                 :             :     {
    3583                 :             :         nLastLayer = nLayer;
    3584                 :             :         nNumLast++;
    3585                 :             :     }
    3586                 :             : #endif
    3587         [ +  + ]:          14 :     if (1 == nNumLast)
    3588                 :             :     {
    3589                 :           7 :         return nLastLayer;
    3590                 :             :     }
    3591                 :             : 
    3592                 :           7 :     return 0;
    3593                 :             : }
    3594                 :             : 
    3595                 :             : 
    3596                 :             : /*#define QZFIX_OK(X) (!(X))*/
    3597                 :             : 
    3598                 :             : 
    3599                 :             : 
    3600                 :             : /********************** CanonGraph *************************************
    3601                 :             :  *   A naive implementation of graph canonical numbering algorithm     *
    3602                 :             :  *   from "Practical Graph Isomorphism" by Brendan D. McKay,           *
    3603                 :             :  *   Congressus Numerantium, Vol. 30 (1981), pp. 45 - 87.              *
    3604                 :             :  *   Note: Several typos fixed, added chem. struct. specifics          *
    3605                 :             :  ***********************************************************************/
    3606                 :             : 
    3607                 :             : /* on entry: pi[0] is equitable */
    3608                 :             : /*******************************************************10/21/2003******
    3609                 :             :  * Later add optimization: if Aut(G) <= Aut(G0) due to some additional *
    3610                 :             :  * layer of coloring applied to G and the following is known about G0: *                                                    *
    3611                 :             :  *                                                                     *
    3612                 :             :  * 0) canonical numbering of G should be same as that of G0            *
    3613                 :             :  *                                                                     *
    3614                 :             :  * 1) canonical numbering as v= v0[n] {vertex number v from            *
    3615                 :             :  *                                     G0 canonical number n)          *
    3616                 :             :  * 2) orbits of Aut(G0) as UnorderedPartition theta0                   *
    3617                 :             :  *                                                                     *
    3618                 :             :  * then when choosing next v[i] for refining the partition consider    *
    3619                 :             :  * only vertices from the Aut(G0) orbit of V(i), that is, only such    *
    3620                 :             :  * v[i] that:                                                          *
    3621                 :             :  *                                                                     *
    3622                 :             :  *       GetUnorderedPartitionMcrNode( &theta0, v[i] ) ==              *
    3623                 :             :  *       GetUnorderedPartitionMcrNode( &theta0, v0[i] )                *
    3624                 :             :  ***********************************************************************/
    3625                 :             : 
    3626                 :             : 
    3627                 :         175 : int CanonGraph( INCHI_CLOCK *ic,
    3628                 :             :                 CANON_GLOBALS *pCG,
    3629                 :             :                 int n,
    3630                 :             :                 int n_tg,
    3631                 :             :                 int n_max,
    3632                 :             :                 int bDigraph,
    3633                 :             :                 Graph *G,
    3634                 :             :                 Partition pi[],
    3635                 :             :                 AT_RANK *nSymmRank,
    3636                 :             :                 AT_RANK *nCanonRank,
    3637                 :             :                 AT_NUMB *nAtomNumberCanon,
    3638                 :             :                 CANON_DATA *pCD,
    3639                 :             :                 CANON_COUNTS *pCC,
    3640                 :             :                 ConTable **pp_zb_rho_inp,
    3641                 :             :                 ConTable **pp_zb_rho_out,
    3642                 :             :                 int LargeMolecules )
    3643                 :             : {
    3644                 :             : 
    3645                 :             :     /* bDigraph != 0
    3646                 :             :        means consider edges from atoms to t-groups
    3647                 :             :        as directed, that is, do not include
    3648                 :             :        t-group ranks in comparing neighbors
    3649                 :             :        when refining partition
    3650                 :             :     */
    3651                 :             : 
    3652                 :             :     /* Always set
    3653                 :             :        lab = true
    3654                 :             :        dig = true
    3655                 :             :     */
    3656                 :             : 
    3657                 :             :     /* in the comments:
    3658                 :             :         m = |zeta|
    3659                 :             :         r = |rho|
    3660                 :             : 
    3661                 :             :         m < n or r < n in case pi[k] in P (i.e. satisfies Lemma 2.25)
    3662                 :             : 
    3663                 :             :         Just after passing point B:
    3664                 :             :         ===========================
    3665                 :             :         K = k-1
    3666                 :             :         wi = v[i], i = 1..K
    3667                 :             :         Gamma(0) = Gamma = Aut(G)pi
    3668                 :             :         Gamma(i) = Gamma(w1,w2,...,wi) pointwise stabilizer for i=1..K
    3669                 :             :         zeta is a terminal node =>
    3670                 :             :           the coarsest equitable partition that fixes w1,...,wK is discrete =>
    3671                 :             :             Gamma(K)=1
    3672                 :             :         At point A only:
    3673                 :             :             index = |Gamma(k-1)|/|Gamma(k)|
    3674                 :             :         At points A and B:
    3675                 :             :             size  = |Gamma(k-1)|
    3676                 :             :             theta = theta(Gamma(k-1));
    3677                 :             :             Gamma(k-1) = <Y>, where Y is the set of all automprhisms output up
    3678                 :             :               to the present stage (in Step 10 = L10 )
    3679                 :             :             |Y| <= n - |theta|
    3680                 :             :     */
    3681                 :             : 
    3682                 :         175 :     AT_RANK    *pCt = pCD->LinearCT;
    3683                 :             :     /*int         nMaxLenCt        =  pCD->nMaxLenLinearCT;*/
    3684                 :         175 :     int        *nLenCt = &pCD->nLenLinearCT;
    3685                 :         175 :     CANON_DATA *pCD1 = pCD;
    3686                 :             : 
    3687                 :         175 :     int i, k, k2, index, l, ok, ret = 0, res;
    3688                 :             :     int t_Lemma;   /* hh: if pi[k-1] satisfies Lemma 2-25 then
    3689                 :             :                           t_Lemma = min{i| i=1..k && pi[i-1] satisfies Lemma 2-25}*/
    3690                 :             :                    /* otherwise t_Lemma = k --> here this is always the case */
    3691                 :             :     int t_eq_zeta; /* ht: min{i|i=1..m && all terminal modes descended from or equal
    3692                 :             :                       to zeta(i) have been shown to be equivalent}. */
    3693                 :             :     int h_zeta;    /* h: the longest common ancestor of zeta and nu is nu(h_zeta) */
    3694                 :             :     int h_rho;     /* hb: the longest common ancestor of rho and nu is nu(h_rho) */
    3695                 :             :     int hz_rho;    /* hzb: max{i|i=1..min(k,r) && Lambda(G,pi,nu(i)) == Lambda(G,pi,rho(i))} */
    3696                 :             :     int hz_zeta;   /* hzf: max{i|i=1..min(k,m) && Lambda(G,pi,nu(i)) == Lambda(G,pi,zeta(i))} */
    3697                 :             :     int qzb_rho;   /* Ct(Lambda[k]) - Ct(rho[k]) */
    3698                 :             :     double size;   /* |Aut(G)| */
    3699                 :             : 
    3700                 :             : 
    3701                 :         175 :     int  nNumLayers = ( NULL != pCD->NumH ) + ( NULL != pCD->NumHfixed ) +
    3702                 :             :                       /* (bDigraph && pCD->nLenLinearCT > pCD->nLenCTAtOnly)*/ /* ??? tautomeric */
    3703                 :         175 :                       ( NULL != pCD->iso_sort_key )
    3704                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    3705                 :             :                     + ( NULL != pCD->iso_sort_key_Hfixed )
    3706                 :             : #endif
    3707                 :             :                     ;
    3708                 :             : 
    3709                 :             : 
    3710   [ +  +  -  + ]:         175 :     int  dig = ( bDigraph || nNumLayers );
    3711   [ +  +  -  + ]:         175 :     int  bSplitTautCompare = ( bDigraph || nNumLayers ); /* compare taut. H and tgroups connections after H */
    3712                 :             :                         /* digraph: 1=>do not use Lemma 2.25, 0 => use */
    3713                 :         175 :     int  lab = 1;       /* label: 1=>find canonical numbering;
    3714                 :             :                             0=>do not find canonical numbering, do not use rho */
    3715                 :             :     int  r;             /* |rho| */
    3716                 :         175 :     int  bZetaEqRho = lab;
    3717                 :             :     int  bZetaIsomorph;
    3718                 :             : 
    3719                 :             :     /*const int L = MAX_SET_SIZE;*/
    3720                 :         175 :     int L_curr_max_set_size = MAX_SET_SIZE;
    3721                 :             : 
    3722                 :             :     UnorderedPartition theta, theta_from_gamma;
    3723                 :             : 
    3724                 :             :     Cell *W;  /* W[i] is the first non-trivial cell of pi[i+1] */
    3725                 :             :     Node *v;  /* v[i] is in W[i] to create T(G,pi,nu[i+1]) */
    3726                 :             :     Node tvc, tvh;
    3727                 :         175 :     S_CHAR *e, *qzb = NULL;   /* qzb = NULL always */
    3728                 :             : 
    3729                 :             :     /* current node CT */
    3730                 :             :     ConTable Lambda;
    3731                 :             :     /* first leaf CT */
    3732                 :             :     ConTable zf_zeta; /* Ct for zeta,  the first discovered terminal node */
    3733                 :             :     /* best leaf/node CT: find the greatest pzb_rho possibly subject to pzb_rho[k] <= pzb_rho_fix[k] condition */
    3734                 :         175 :     ConTable *pzb_rho = NULL;  /* Ct for rho,   the best discovered terminal node */
    3735                 :             :     /* fixed input CT: for all k pzb_rho[k] <= pzb_rho_fix[k]; at the end pzb_rho == pzb_rho_fix */
    3736   [ +  +  +  - ]:         175 :     ConTable *pzb_rho_fix = ( pp_zb_rho_inp && *pp_zb_rho_inp ) ? *pp_zb_rho_inp : NULL;
    3737                 :             : 
    3738                 :             :     NodeSet Omega; /* MAX_SET_SIZE */
    3739                 :             :     NodeSet Phi;   /* MAX_SET_SIZE */
    3740                 :             :     NodeSet cur_nodes;   /* 1 each */
    3741                 :             : 
    3742                 :             :     Transposition gamma;
    3743                 :             : 
    3744                 :             :     Partition zeta;      /* the first discovered terminal node */
    3745                 :             :     Partition rho;       /* the best discovered terminal node */
    3746                 :             : 
    3747                 :         175 :     int nNumFoundGenerators = 0;
    3748                 :         175 :     int qzb_rho_fix = 0;
    3749                 :         175 :     int hzb_rho_fix = 0;
    3750                 :         175 :     int bRhoIsDiscrete = 1;
    3751                 :             :     kLeast kLeast_rho[MAX_LAYERS];
    3752                 :             :     kLeast kLeast_rho_fix[MAX_LAYERS];
    3753                 :             :     int nOneAdditionalLayer;
    3754                 :         175 :     int pzb_rho_fix_reached = 0;
    3755                 :         175 :     int L_rho_fix_prev = 0, I_rho_fix_prev = -1, k_rho_fix_prev = 0;
    3756                 :             : 
    3757         [ +  - ]:         175 :     if (!LargeMolecules)
    3758                 :             :     {
    3759                 :         175 :         L_curr_max_set_size = NORMALLY_ALLOWED_MAX_SET_SIZE;
    3760                 :             :     }
    3761                 :             : 
    3762                 :             : 
    3763                 :             :     /* Note: Layered comparison should be consistent, especially in layer numbers.
    3764                 :             :              Layered comparison is implemented in:
    3765                 :             :                      CtFullCompare()
    3766                 :             :                      CtPartCompare()
    3767                 :             :                      GetOneAdditionalLayer()
    3768                 :             : 
    3769                 :             :              The partial comparison results in kLeast[] are used in
    3770                 :             :                      CtFullCompareLayers()
    3771                 :             :                      CtPartCompareLayers()
    3772                 :             :                      CtCompareLayersGetFirstDiff()
    3773                 :             :                      UpdateCompareLayers()
    3774                 :             :      */
    3775                 :             : 
    3776                 :             : 
    3777                 :         175 :     nOneAdditionalLayer = GetOneAdditionalLayer( pCD1, pzb_rho_fix );
    3778                 :             : 
    3779                 :             : 
    3780                 :             :     /* next 2 lines for debug only */
    3781                 :             :     /* num_g++;  */
    3782                 :             :     /* WriteGraph( G, n_tg, num_g, "V:\\IChI_v10\\Gordon-Graphs\\hard\\k06g08v312-alt.dre", "a+" ); */
    3783                 :             : 
    3784                 :             :     /* memory allocation */
    3785                 :             : 
    3786         [ -  + ]:         175 :     if (0 > SetBitCreate( pCG ))
    3787                 :             :     {
    3788                 :           0 :         return -1;
    3789                 :             :     }
    3790   [ +  +  -  + ]:         175 :     if (pzb_rho_fix && pzb_rho_fix->nLenCTAtOnly != pCD->nLenCTAtOnly)
    3791                 :             :     {
    3792                 :             :         /* consistency check */
    3793                 :           0 :         return -2;
    3794                 :             :     }
    3795                 :         175 :     ok = 1;
    3796                 :             : 
    3797                 :         175 :     ok &= UnorderedPartitionCreate( &theta, n_tg );
    3798                 :         175 :     ok &= UnorderedPartitionCreate( &theta_from_gamma, n_tg );
    3799                 :             : 
    3800                 :             :     /* djb-rwth: fixing dereferencing NULL pointer and buffer overflows */
    3801                 :         175 :     W = (Cell*) inchi_calloc( n_tg, sizeof( W[0] ) );
    3802                 :         175 :     v = (Node*) inchi_calloc( n_tg, sizeof( v[0] ) );
    3803                 :         175 :     e = (S_CHAR*) inchi_calloc( n_tg, sizeof( e[0] ) );
    3804                 :             : 
    3805   [ +  -  +  -  :         175 :     if (!W || !v || !e)
                   -  + ]
    3806                 :             :     {
    3807                 :           0 :         ok &= 0;
    3808                 :             :     }
    3809                 :             : 
    3810                 :             : /*
    3811                 :             :     ok &= ( NULL != ( W = (Cell*) inchi_calloc( n_tg, sizeof( W[0] ) ) ) );
    3812                 :             :     ok &= ( NULL != ( v = (Node*) inchi_calloc( n_tg, sizeof( v[0] ) ) ) );
    3813                 :             :     ok &= ( NULL != ( e = (S_CHAR*) inchi_calloc( n_tg, sizeof( e[0] ) ) ) );
    3814                 :             : */
    3815                 :             :     /*
    3816                 :             :     ok &= (NULL != (v   = (Node*)inchi_calloc( n_tg, sizeof(W[0]))));
    3817                 :             :     ok &= (NULL != (e   = (S_CHAR*)inchi_calloc( n_tg, sizeof(W[0]))));
    3818                 :             :     */
    3819                 :             : 
    3820                 :             :     /*    ok &= (NULL != (qzb = (S_CHAR*)inchi_calloc( n_tg, sizeof(W[0])))); */
    3821                 :         175 :     ok &= CTableCreate( &Lambda, n, pCD );
    3822                 :         175 :     ok &= CTableCreate( &zf_zeta, n, pCD );
    3823   [ +  -  +  - ]:         350 :     ok &= ( ( pzb_rho = (ConTable *) inchi_calloc( 1, sizeof( *pzb_rho ) ) ) &&
    3824                 :         175 :             CTableCreate( pzb_rho, n, pCD ) );
    3825                 :             : 
    3826                 :         175 :     ok &= NodeSetCreate( pCG, &Omega, n_tg, L_curr_max_set_size );
    3827                 :         175 :     ok &= NodeSetCreate( pCG, &Phi, n_tg, L_curr_max_set_size );
    3828                 :         175 :     ok &= NodeSetCreate( pCG, &cur_nodes, n_tg, 1 );
    3829                 :             : 
    3830                 :         175 :     ok &= PartitionCreate( &zeta, n_tg );
    3831                 :         175 :     ok &= PartitionCreate( &rho, n_tg );
    3832                 :         175 :     ok &= TranspositionCreate( &gamma, n_tg );
    3833                 :             : 
    3834                 :             :     INCHI_HEAPCHK
    3835                 :             : 
    3836                 :             : /*L1:*/
    3837                 :         175 :     k = 1;
    3838                 :         175 :     size = 1.0;
    3839                 :         175 :     hz_rho = index = l = 0; /* djb-rwth: removing redundant code */
    3840                 :             : 
    3841         [ -  + ]:         175 :     if (!ok)
    3842                 :             :     {
    3843                 :           0 :         goto exit_function; /* initialization failed */
    3844                 :             :     }
    3845                 :             : 
    3846                 :         175 :     UnorderedPartitionMakeDiscrete( &theta, n_tg );
    3847                 :         175 :     t_Lemma = 2;
    3848                 :             : 
    3849                 :         175 :     pCC->lNumBreakTies = 0;
    3850                 :         175 :     pCC->lNumDecreasedCT = 0;
    3851                 :         175 :     pCC->lNumRejectedCT = 0;
    3852                 :         175 :     pCC->lNumEqualCT = 1;
    3853                 :         175 :     pCC->lNumTotCT = 0;
    3854                 :             :     /* djb-rwth: removing redundant code */
    3855                 :             : 
    3856                 :         175 :     hzb_rho_fix = 1;
    3857                 :             : 
    3858                 :         175 :     memset( kLeast_rho, 0, sizeof( kLeast_rho ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    3859                 :         175 :     memset( kLeast_rho_fix, 0, sizeof( kLeast_rho_fix ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    3860                 :             : 
    3861         [ +  + ]:         175 :     if (PartitionIsDiscrete( &pi[k - 1], n_tg ))
    3862                 :             :     {
    3863                 :             :         /* added the following 3 lines to the original to create Ct */
    3864                 :         143 :         PartitionCopy( &rho, &pi[k - 1], n_tg );
    3865                 :         143 :         CtPartFill( G, pCD, &pi[k - 1], pzb_rho, 1, n, n_tg, n_max );
    3866                 :         143 :         CtPartINCHI_CANON_INFINITY( pzb_rho, qzb, 2 );
    3867                 :         143 :         pCC->lNumTotCT++;
    3868                 :             :         /* djb-rwth: removing redundant code */
    3869                 :             :         /* goto L18; */
    3870                 :         143 :         goto exit_function;
    3871                 :             :     }
    3872                 :             : 
    3873   [ +  +  +  + ]:          32 :     if (!dig && PartitionSatisfiesLemma_2_25( &pi[0], n ))
    3874                 :             :     {
    3875                 :          22 :         t_Lemma = 1;
    3876                 :             :     }
    3877                 :             : 
    3878                 :             :     /*
    3879                 :             :     PartitionGetFirstCell( &pi[k-1], &W[k-1], k, n );
    3880                 :             :     v[k-1] = CellGetMinNode( &pi[k-1], &W[k-1], 0, pCD1 );
    3881                 :             :     CtPartClear( &Lambda, 1 );
    3882                 :             :     e[k-1] = 0;
    3883                 :             :     */
    3884                 :          32 :     CtPartClear( &Lambda, 1 );
    3885                 :             :     INCHI_HEAPCHK
    3886                 :             : 
    3887                 :             : /* L2: reach the first leaf and save it in zeta and rho */
    3888         [ +  - ]:          72 :     while (k)
    3889                 :             :     {
    3890                 :             :         /* the two next lines intentionally switched */
    3891                 :             :         /* Create equitable partition in pi[k]  */
    3892                 :          72 :         PartitionGetFirstCell( &pi[k - 1], W, k, n );
    3893                 :          72 :         v[k - 1] = CellGetMinNode( &pi[k - 1], &W[k - 1], 0, pCD1 );
    3894                 :          72 :         e[k - 1] = 0;
    3895   [ +  +  +  + ]:          72 :         if (dig || !PartitionSatisfiesLemma_2_25( &pi[k - 1], n ))
    3896                 :             :         {
    3897                 :          26 :             t_Lemma = k + 1;
    3898                 :             :         }
    3899                 :             :         /* e[k-1] = 0; */
    3900                 :             :         {
    3901                 :          72 :             Node vv = v[k - 1];
    3902         [ -  + ]:          72 :             if (0 > ( ret = PartitionColorVertex( pCG, G, &pi[k - 1], vv /*v[k-1]*/, n, n_tg, n_max, bDigraph, 0 ) ))
    3903                 :             :             {
    3904                 :           0 :                 goto exit_error;
    3905                 :             :             }
    3906                 :             :         }
    3907                 :          72 :         pCC->lNumBreakTies++;
    3908                 :          72 :         k++;
    3909                 :             : 
    3910                 :          72 :         CtPartFill( G, pCD, &pi[k - 1], &Lambda, k - 1, n, n_tg, n_max);
    3911                 :             : 
    3912                 :             :         /* return -1; *//* debug only */
    3913                 :             :         /* if(h_zeta==0)goto L5; L5: */
    3914                 :             :         /* the first terminal node has not been reached yet */
    3915                 :             :         /* search for the predefined numbering */
    3916   [ +  +  +  - ]:          72 :         if (pzb_rho_fix && QZFIX_OK( qzb_rho_fix ))
    3917                 :             :         {
    3918                 :          21 :             qzb_rho_fix = CtPartCompare( &Lambda, pzb_rho_fix, qzb, kLeast_rho_fix, k - 1, 1, bSplitTautCompare );
    3919         [ +  - ]:          21 :             if (QZFIX_OK( qzb_rho_fix ))
    3920                 :             :             {
    3921                 :          21 :                 hzb_rho_fix = k;
    3922                 :             :             }
    3923                 :             :         }
    3924                 :             : 
    3925   [ +  -  +  - ]:          72 :         if (lab && QZFIX_OK( qzb_rho_fix ))  /* DCh */
    3926                 :          72 :             CtPartCopy( pzb_rho, &Lambda, k - 1 );
    3927                 :          72 :         CtPartCopy( &zf_zeta, &Lambda, k - 1 );
    3928                 :             :         /*goto L4; L4:*/
    3929         [ +  + ]:          72 :         if (PartitionIsDiscrete( &pi[k - 1], n ))
    3930                 :             :         {
    3931                 :          32 :             break;  /* goto L7; */
    3932                 :             :         }
    3933                 :             :         /* goto L2; */
    3934                 :             :     }
    3935                 :             : 
    3936                 :          32 :     pCC->lNumTotCT++;
    3937                 :             : 
    3938                 :             :     /* L7; L7: */
    3939                 :             :     /* if ( h_zeta == 0 ) goto L18; L18:*/
    3940                 :          32 :     h_zeta = t_eq_zeta = hz_zeta = k;
    3941                 :          32 :     CtPartINCHI_CANON_INFINITY( &zf_zeta, NULL, k );
    3942                 :             :     /******************** <<<===== B **************************/
    3943                 :          32 :     PartitionCopy( &zeta, &pi[k - 1], n_tg );
    3944         [ +  - ]:          32 :     if (lab)
    3945                 :             :     {
    3946         [ +  + ]:          32 :         if (pzb_rho_fix)
    3947                 :             :         {
    3948         [ +  - ]:           7 :             if (0 == qzb_rho_fix)
    3949                 :             :             {
    3950                 :           7 :                 qzb_rho_fix = CtFullCompare( &Lambda, pzb_rho_fix, 1, bSplitTautCompare );
    3951         [ -  + ]:           7 :                 if (qzb_rho_fix > 0)
    3952                 :             :                 {
    3953                 :           0 :                     hzb_rho_fix = 1;
    3954                 :             :                 }
    3955                 :             :             }
    3956         [ +  - ]:           7 :             if (hzb_rho_fix > 1)
    3957                 :             :             {
    3958                 :           7 :                 PartitionCopy( &rho, &pi[hzb_rho_fix - 1], n_tg );
    3959                 :             :                 /*CtPartINCHI_CANON_INFINITY( pzb_rho, qzb, k );*/
    3960                 :             :             }
    3961                 :           7 :             hz_rho = h_rho = hzb_rho_fix;
    3962                 :           7 :             bRhoIsDiscrete = ( hzb_rho_fix == k );
    3963         [ +  - ]:           7 :             if (bRhoIsDiscrete)
    3964                 :             :             {
    3965                 :           7 :                 CtPartINCHI_CANON_INFINITY( pzb_rho, qzb, k );
    3966                 :           7 :                 pzb_rho_fix_reached = !qzb_rho_fix;
    3967                 :           7 :                 CtCompareLayersGetFirstDiff( kLeast_rho_fix, nOneAdditionalLayer,
    3968                 :             :                                  &L_rho_fix_prev, &I_rho_fix_prev, &k_rho_fix_prev );
    3969                 :             :             }
    3970                 :             : 
    3971                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    3972                 :             :             else
    3973                 :             :             {
    3974                 :             :                 int stop = 1;
    3975                 :             :             }
    3976                 :             : #endif
    3977                 :             :         }
    3978                 :             :         else
    3979                 :             :         {
    3980                 :          25 :             PartitionCopy( &rho, &pi[k - 1], n_tg );
    3981                 :          25 :             hz_rho = h_rho = k;
    3982                 :          25 :             CtPartINCHI_CANON_INFINITY( pzb_rho, qzb, k );
    3983                 :             :         }
    3984                 :          32 :         qzb_rho = 0;
    3985                 :             :     }
    3986                 :             : 
    3987                 :          32 :     r = k;
    3988                 :          32 :     v[k - 1] = INCHI_CANON_INFINITY;     /* DCh */
    3989                 :          32 :     CellMakeEmpty( W, k ); /* DCh */
    3990                 :          32 :     k--;
    3991                 :          32 :     goto L13;
    3992                 :             : 
    3993                 :             : 
    3994                 :         147 : L2:
    3995                 :             :     /* the two next lines intentionally switched */
    3996                 :             :     /* Create equitable partition in pi[k]  */
    3997         [ -  + ]:         147 :     if (0 > ( ret = PartitionColorVertex( pCG, G, &pi[k - 1], v[k - 1],
    3998                 :             :         n, n_tg, n_max, bDigraph, 0 ) ))
    3999                 :             :     {
    4000                 :           0 :         goto exit_error;
    4001                 :             :     }
    4002                 :         147 :     pCC->lNumBreakTies++;
    4003                 :         147 :     k++;
    4004                 :         147 :     CtPartFill( G, pCD, &pi[k - 1], &Lambda, k - 1, n, n_tg, n_max );
    4005                 :         147 :     e[k - 1] = 0;         /* moved  */
    4006                 :         147 :     v[k - 1] = INCHI_CANON_INFINITY;  /* added by DCh. */
    4007                 :         147 :     CellMakeEmpty( W, k ); /* DCh */
    4008                 :             : 
    4009   [ +  -  +  - ]:         294 :     if (hz_zeta == k - 1 &&
    4010                 :         147 :          0 == CtPartCompare( &Lambda, &zf_zeta, NULL, NULL, k - 1, 0, bSplitTautCompare ))
    4011                 :             :     {
    4012                 :         147 :         hz_zeta = k; /* max{k|Lambda(G,pi,nu(k))==Lambda(G,pi,zeta) }  */
    4013                 :             :     } /* added */
    4014                 :             : 
    4015                 :             : 
    4016                 :             :     /* -- old code ---
    4017                 :             :     if ( pzb_rho_fix && QZFIX_OK(qzb_rho_fix) ) {
    4018                 :             :         qzb_rho_fix = CtPartCompare( &Lambda, pzb_rho_fix, qzb, kLeast_rho_fix, k-1, 1, bSplitTautCompare );
    4019                 :             :         if ( QZFIX_OK(qzb_rho_fix) ) {
    4020                 :             :             hzb_rho_fix = k;
    4021                 :             :         } else {
    4022                 :             :             pCC->lNumRejectedCT ++;
    4023                 :             :         }
    4024                 :             :     }
    4025                 :             :     */
    4026                 :             : 
    4027                 :             :     /* --- new code ---*/
    4028   [ +  +  +  - ]:         147 :     if (pzb_rho_fix && !qzb_rho_fix)
    4029                 :             :     {
    4030                 :          50 :         qzb_rho_fix = CtPartCompare( &Lambda, pzb_rho_fix, qzb, kLeast_rho_fix, k - 1, 1, bSplitTautCompare );
    4031   [ +  -  +  - ]:          50 :         if (!qzb_rho_fix && bRhoIsDiscrete)
    4032                 :             :         {
    4033                 :          50 :             qzb_rho_fix = CtPartCompareLayers( kLeast_rho_fix, L_rho_fix_prev, nOneAdditionalLayer );
    4034                 :             : 
    4035                 :             : #if ( FIX_ChCh_CONSTIT_CANON_BUG == 1 )
    4036         [ -  + ]:          50 :             if (qzb_rho_fix)
    4037                 :             :             {
    4038                 :           0 :                 int L_rho_fix_diff = abs( qzb_rho_fix ) - 1;
    4039   [ #  #  #  # ]:           0 :                 if (L_rho_fix_diff < L_rho_fix_prev ||
    4040   [ #  #  #  # ]:           0 :                      (L_rho_fix_diff == (L_rho_fix_prev && kLeast_rho_fix[L_rho_fix_diff].i < I_rho_fix_prev))) /* djb-rwth: addressing LLVM warning */
    4041                 :             :                 {
    4042                 :           0 :                     qzb_rho_fix = L_rho_fix_diff + 1; /* positive difference will be rejected */
    4043                 :             :                 }
    4044                 :             :             }
    4045                 :             : #endif
    4046                 :             : 
    4047                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    4048                 :             :             if (qzb_rho_fix)
    4049                 :             :             {
    4050                 :             :                 int stop = 1; /* debug only */
    4051                 :             :             }
    4052                 :             : #endif
    4053                 :             :         }
    4054         [ -  + ]:          50 :         if (!QZFIX_OK( qzb_rho_fix ))
    4055                 :             :         {
    4056                 :           0 :             pCC->lNumRejectedCT++;
    4057                 :             :         }
    4058                 :             :     }
    4059   [ +  +  +  - ]:         147 :     if (pzb_rho_fix && QZFIX_OK( qzb_rho_fix ))
    4060                 :             :     {
    4061                 :          50 :         hzb_rho_fix = k;
    4062                 :             :     }
    4063                 :             :     /* if (!lab) goto L3; */
    4064   [ +  -  +  - ]:         147 :     if (lab && QZFIX_OK( qzb_rho_fix ))
    4065                 :             :     {
    4066                 :             :         /* once the difference has been found it is meaningful as long as k increments */
    4067                 :             :         /* cur_qzb2 = CtPartCompare( &Lambda, pzb_rho, qzb, k-1 ); */ /* rho compare */
    4068   [ +  -  +  -  :         147 :         if (hz_rho == k - 1 && !qzb_rho && bRhoIsDiscrete)
                   +  - ]
    4069                 :             :         {
    4070                 :         147 :             int qzb_rho_temp = 0; /* djb-rwth: ignoring LLVM warning: variable used */
    4071                 :         147 :             qzb_rho = CtPartCompare( &Lambda, pzb_rho, qzb, kLeast_rho, k - 1, 0, bSplitTautCompare );
    4072                 :             :             /* old code */
    4073   [ +  -  +  +  :         147 :             if (!qzb_rho && pzb_rho_fix_reached &&
                   +  - ]
    4074         [ -  + ]:          50 :                   nOneAdditionalLayer && 0 > kLeast_rho[nOneAdditionalLayer].k)
    4075                 :             :             {
    4076                 :           0 :                 qzb_rho_temp = -( nOneAdditionalLayer + 1 ); /* djb-rwth: ignoring LLVM warning: variable used */
    4077                 :             :                 /* qzb_rho = -(nOneAdditionalLayer+1); *//* early rejection */
    4078                 :             :             }
    4079                 :             :             /* new code */
    4080   [ +  -  +  - ]:         147 :             if (!qzb_rho && bRhoIsDiscrete)
    4081                 :             :             {
    4082                 :         147 :                 qzb_rho = CtPartCompareLayers( kLeast_rho, L_rho_fix_prev, 0 );
    4083                 :             : #if ( FIX_ChCh_CONSTIT_CANON_BUG == 1 )
    4084         [ -  + ]:         147 :                 if (qzb_rho)
    4085                 :             :                 {
    4086                 :           0 :                     int L_rho_diff = abs( qzb_rho ) - 1;
    4087   [ #  #  #  # ]:           0 :                     if (L_rho_diff < L_rho_fix_prev ||
    4088   [ #  #  #  # ]:           0 :                          (L_rho_diff == (L_rho_fix_prev && kLeast_rho[L_rho_diff].i < I_rho_fix_prev))) /* djb-rwth: addressing LLVM warning */
    4089                 :             :                     {
    4090                 :           0 :                         qzb_rho = -( L_rho_diff + 1 ); /* negative difference will be rejected */
    4091                 :             :                     }
    4092                 :             :                 }
    4093                 :             : #endif
    4094                 :             :             }
    4095                 :             :             /* compare old results to new */
    4096                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    4097                 :             :             if (qzb_rho_temp && qzb_rho_temp != qzb_rho)
    4098                 :             :             {
    4099                 :             :                 int stop = 1; /* <BRKPT> */
    4100                 :             :             }
    4101                 :             : #endif
    4102         [ +  - ]:         147 :             if (!qzb_rho)
    4103                 :             :             {
    4104                 :         147 :                 hz_rho = k;
    4105                 :             :             }
    4106                 :             :             else
    4107                 :             :             {
    4108         [ #  # ]:           0 :                 if (qzb_rho < 0)
    4109                 :             :                 {
    4110                 :           0 :                     pCC->lNumRejectedCT++;
    4111                 :             :                 }
    4112                 :             :             }
    4113                 :             :         }
    4114   [ +  -  +  -  :         147 :         if (qzb_rho > 0 || (!qzb_rho && !bRhoIsDiscrete)) /* djb-rwth: addressing LLVM warning */
                   -  + ]
    4115                 :             :         {
    4116                 :             :             /* found better rho */
    4117         [ #  # ]:           0 :             if (!nNumLayers)
    4118                 :             :             {
    4119                 :           0 :                 CtPartCopy( pzb_rho, &Lambda, k - 1 );
    4120                 :             :             }
    4121                 :             :         }
    4122                 :             :     }
    4123                 :             : 
    4124                 :             : 
    4125                 :             : /*L3:*/
    4126                 :             :     /*if ( hz_rho == k || (lab && qzb_rho >= 0 ) )*/
    4127                 :             :     /*if ( hz_zeta == k || hz_rho == k || (lab && qzb_rho >= 0 ) ) goto L4; else goto L6;*/
    4128   [ -  +  -  -  :         147 :     if (hz_zeta == k || hz_rho == k ||
                   -  - ]
    4129   [ #  #  #  # ]:           0 :         ( lab && qzb_rho >= 0 && QZFIX_OK( qzb_rho_fix ) ))
    4130                 :             :     {
    4131                 :             :         /*L4: check for possible isomorphism or found a better rho */
    4132         [ +  + ]:         147 :         if (PartitionIsDiscrete( &pi[k - 1], n ))
    4133                 :             :         {
    4134                 :          73 :             pCC->lNumTotCT++;
    4135                 :          73 :             goto L7;
    4136                 :             :         }
    4137                 :          74 :         PartitionGetFirstCell( &pi[k - 1], W, k, n );
    4138                 :          74 :         v[k - 1] = CellGetMinNode( &pi[k - 1], &W[k - 1], 0, pCD1 );
    4139   [ +  +  +  + ]:          74 :         if (!dig && PartitionSatisfiesLemma_2_25( &pi[k - 1], n ))
    4140                 :             :         {
    4141                 :             :             ; /* found additional isomprphism */
    4142                 :             :         }
    4143                 :             :         else
    4144                 :             :         {
    4145                 :          31 :             t_Lemma = k + 1;
    4146                 :             :         }
    4147                 :          74 :         e[k - 1] = 0;  /* created new cell W[k-1] */
    4148                 :          74 :         goto L2;
    4149                 :             :     }
    4150                 :             : 
    4151                 :             : 
    4152                 :           0 : L6:
    4153                 :             :     /* a better rho or no good node was found at this level; return to smaller k */
    4154                 :           0 :     k2 = k;
    4155         [ #  # ]:           0 :     k = inchi_min( t_Lemma - 1, inchi_max( t_eq_zeta - 1, hz_rho ) );
    4156         [ #  # ]:           0 :     if (k2 == t_Lemma)
    4157                 :             :     {
    4158                 :           0 :         goto L13;
    4159                 :             :     }
    4160                 :             : 
    4161                 :             :     /* store isomorphism found from Lemma 2.25. should be dig=0 !!! */
    4162         [ #  # ]:           0 :     if (dig)
    4163                 :             :     {
    4164                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    4165                 :             :         int stop = 1;
    4166                 :             : #endif
    4167                 :           0 :         goto L13;
    4168                 :             :     }
    4169                 :             : 
    4170                 :           0 :     l = inchi_min( l + 1, L_curr_max_set_size );
    4171                 :           0 :     PartitionGetMcrAndFixSet( pCG, &pi[t_Lemma - 1], &Omega, &Phi, n_tg, l );
    4172                 :           0 :     goto L12;
    4173                 :             : 
    4174                 :             : 
    4175                 :             : 
    4176                 :          73 : L7:
    4177                 :             :     /* from L4: pi[k-1] is discrete */
    4178         [ -  + ]:          73 :     if (h_zeta == 0)
    4179                 :             :     {
    4180                 :             :         /*goto L18;*/  /* error. the first T(nu) leaf was found */
    4181                 :           0 :         ret = CT_CANON_ERR;
    4182                 :           0 :         goto exit_error;
    4183                 :             :     }
    4184         [ -  + ]:          73 :     if (k != hz_zeta)
    4185                 :             :     {
    4186                 :           0 :         goto L8;
    4187                 :             :     }
    4188                 :             :     /*  here zeta^gamma == nu */
    4189                 :             :     /*  if ( G^gamma == G ) goto L10; */
    4190         [ +  - ]:          73 :     if (0 == ( res = CtFullCompare( &Lambda, &zf_zeta, 0, bSplitTautCompare ) )) /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    4191                 :             :     {
    4192                 :          73 :         PartitionGetTransposition( &zeta, &pi[k - 1], n_tg, &gamma );
    4193                 :          73 :         bZetaIsomorph = 1; /* for testing only */
    4194                 :             :         /* djb-rwth: removing redundant code */
    4195                 :          73 :         goto L10;
    4196                 :             :     }
    4197                 :             :     else
    4198                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    4199                 :             :     {
    4200                 :             :         int stop = 1;
    4201                 :             :     }
    4202                 :             : #endif
    4203                 :             :     /* !!! we should never come here !!! */
    4204         [ #  # ]:           0 :     if (!nNumLayers)
    4205                 :             :     {
    4206                 :           0 :         ret = -2;
    4207                 :           0 :         goto exit_error;
    4208                 :             :     }
    4209                 :             : 
    4210                 :             : 
    4211                 :           0 : L8: /* here nu is discrete: check rho for being a bettere leaf or isomorphism */
    4212                 :             :     /*if ( !lab || qzb_rho < 0 || !QZFIX_OK(qzb_rho_fix) )*/
    4213   [ #  #  #  #  :           0 :     if (!lab || (qzb_rho < 0 && ( !pzb_rho_fix || qzb_rho_fix > 0 ))) /* djb-rwth: addressing LLVM warning */
             #  #  #  # ]
    4214                 :             :     {
    4215                 :           0 :         goto L6;
    4216                 :             :     }
    4217   [ #  #  #  # ]:           0 :     if (pzb_rho_fix && kLeast_rho_fix && 0 == qzb_rho_fix) /* djb-rwth: addressing of array kLeast_rho_fix will always evaluate to true? */
    4218                 :             :     {
    4219                 :             :         /* check for the rejection condition: Lambda > zb_rho_fix */
    4220                 :             :         if (kLeast_rho_fix) /* djb-rwth: addressing of array kLeast_rho_fix will always evaluate to true? */
    4221                 :             :         {
    4222                 :             :             int qzb_rho_fix_alt;
    4223                 :           0 :             qzb_rho_fix = CtFullCompareLayers( kLeast_rho_fix );
    4224                 :             :             /* for debug only */
    4225                 :           0 :             qzb_rho_fix_alt = CtFullCompare( &Lambda, pzb_rho_fix, 1, bSplitTautCompare );
    4226         [ #  # ]:           0 :             if (qzb_rho_fix != qzb_rho_fix_alt)
    4227                 :             :             {
    4228                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    4229                 :             :                 int stop = 1;
    4230                 :             : #endif
    4231                 :           0 :                 qzb_rho_fix = qzb_rho_fix_alt;
    4232                 :             :             }
    4233                 :             :             /* end debug */
    4234                 :             :         }
    4235                 :             :         else
    4236                 :             :         {
    4237                 :             :             qzb_rho_fix = CtFullCompare( &Lambda, pzb_rho_fix, 1, bSplitTautCompare );
    4238                 :             :         }
    4239         [ #  # ]:           0 :         if (!pzb_rho_fix_reached)
    4240                 :             :         {
    4241                 :           0 :             pzb_rho_fix_reached = !qzb_rho_fix;
    4242                 :             :         }
    4243         [ #  # ]:           0 :         if (0 < qzb_rho_fix)
    4244                 :             :         {
    4245                 :             :             /* Lambda > pzb_rho_fix, ignore this node */
    4246                 :             :             /* hzb_rho_fix = min( hzb_rho_fix, hz_rho ); */ /* ??? */
    4247                 :           0 :             qzb_rho_fix = 0;
    4248                 :           0 :             goto L6;
    4249                 :             :         }
    4250                 :           0 :         qzb_rho_fix = 0;
    4251                 :             :     }
    4252                 :             : 
    4253         [ #  # ]:           0 :     if (qzb_rho < 0)
    4254                 :             :     {
    4255                 :           0 :         goto L6;
    4256                 :             :     }
    4257   [ #  #  #  # ]:           0 :     if (qzb_rho > 0 || !bRhoIsDiscrete)
    4258                 :             :     {
    4259                 :           0 :         goto L9; /* note: p67 says k > PartitionSize( &rho, n ) */
    4260                 :             :     }
    4261         [ #  # ]:           0 :     if (k < r)
    4262                 :             :     {
    4263                 :           0 :         goto L9; /* cannot understand it... */
    4264                 :             :     }
    4265                 :             : 
    4266                 :             :     /* !!! we should never come here if G(nu) != G(rho): CtPartCompare must be enough !!! */
    4267                 :             : 
    4268                 :             :     /* if ( G(nu) > G(rho) ) goto L9; */
    4269                 :             :     if (kLeast_rho) /* djb-rwth: addressing of array kLeast_rho will always evaluate to true? */
    4270                 :             :     {
    4271                 :             :         int cur_qzb_alt;
    4272                 :           0 :         qzb_rho = CtFullCompareLayers( kLeast_rho );
    4273                 :             :         /* for debug only */
    4274                 :           0 :         cur_qzb_alt = CtFullCompare( &Lambda, pzb_rho, 0, bSplitTautCompare );
    4275         [ #  # ]:           0 :         if (qzb_rho != cur_qzb_alt)
    4276                 :             :         {
    4277                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    4278                 :             :             int stop = 1;
    4279                 :             : #endif
    4280                 :           0 :             qzb_rho = cur_qzb_alt;
    4281                 :             :         }
    4282                 :             :         /* end debug */
    4283                 :             :     }
    4284                 :             :     else
    4285                 :             :     {
    4286                 :             :         qzb_rho = CtFullCompare( &Lambda, pzb_rho, 0, bSplitTautCompare );
    4287                 :             :     }
    4288                 :             :     /* qzb_rho difference can be due to layers 1..MAX_LAYERS-1 only */
    4289         [ #  # ]:           0 :     if (0 < qzb_rho)
    4290                 :             :     {
    4291                 :             :         /* CtFullCompare( &Lambda, pzb_rho, 0, bSplitTautCompare ); */
    4292                 :             :         /* djb-rwth: removing redundant code */
    4293                 :           0 :         goto L9;
    4294                 :             :     }
    4295                 :             :     /* if ( G(nu) < G(rho) ) goto L6; */
    4296         [ #  # ]:           0 :     if (0 > qzb_rho)
    4297                 :             :     {
    4298                 :           0 :         qzb_rho = 0;
    4299                 :           0 :         goto L6;
    4300                 :             :     }
    4301                 :             :     /* nu^gamma == rho */
    4302         [ #  # ]:           0 :     if (r != k)
    4303                 :             :     {  /* if() is for debug only */
    4304                 :           0 :         r = k;
    4305                 :             :     }
    4306                 :             : 
    4307                 :           0 :     PartitionGetTransposition( &pi[k - 1], &rho, n_tg, &gamma );
    4308                 :           0 :     bZetaIsomorph = 0; /* DCh */
    4309                 :           0 :     pCC->lNumEqualCT++;
    4310                 :           0 :     goto L10;
    4311                 :             : 
    4312                 :           0 : L9:
    4313                 :             :     /* rho := nu; */
    4314                 :           0 :     PartitionCopy( &rho, &pi[k - 1], n_tg );
    4315         [ #  # ]:           0 :     if (nNumLayers)
    4316                 :             :     {
    4317                 :           0 :         CtFullCopy( pzb_rho, &Lambda );
    4318                 :             :     }
    4319                 :           0 :     bZetaEqRho = 0;
    4320                 :           0 :     qzb_rho = 0;
    4321                 :           0 :     CtCompareLayersGetFirstDiff( kLeast_rho_fix, nOneAdditionalLayer,
    4322                 :             :                                  &L_rho_fix_prev, &I_rho_fix_prev,
    4323                 :             :                                  &k_rho_fix_prev );
    4324                 :           0 :     memset( kLeast_rho, 0, sizeof( kLeast_rho ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4325                 :           0 :     h_rho = hz_rho = k;
    4326                 :           0 :     CtPartINCHI_CANON_INFINITY( pzb_rho, qzb, k );
    4327                 :           0 :     pCC->lNumDecreasedCT++;
    4328                 :           0 :     pCC->lNumEqualCT = 1;
    4329                 :           0 :     bRhoIsDiscrete = 1;
    4330                 :           0 :     goto L6;
    4331                 :             : 
    4332                 :          73 : L10: /* discrete pi[k-1] && G^gamma == G */
    4333   [ -  +  -  -  :          73 :     pCC->lNumEqualCT += bZetaEqRho || !( bZetaIsomorph || qzb_rho );
                   -  - ]
    4334                 :          73 :     l = inchi_min( l + 1, L_curr_max_set_size );
    4335                 :             :     /* Omega[l] := mcr(gamma);
    4336                 :             :        Phi[l]   := fix(gamma);
    4337                 :             :     */
    4338                 :             : 
    4339                 :          73 :     TranspositionGetMcrAndFixSetAndUnorderedPartition( pCG, &gamma, &Omega, &Phi,
    4340                 :             :                                                        n_tg, l, &theta_from_gamma );
    4341                 :             :     /*
    4342                 :             :     if ( theta(gamma) <= theta ) goto L11;
    4343                 :             :     theta := theta v theta(gamma);
    4344                 :             :     UnorderedPartitionJoin() returns 0 if theta_from_gamma is finer than theta,
    4345                 :             :     which means no changes in theta: theta_from_gamma ^ theta == theta.
    4346                 :             :     */
    4347         [ -  + ]:          73 :     if (!UnorderedPartitionJoin( &theta_from_gamma, &theta, n_tg ))
    4348                 :             :     {
    4349                 :           0 :         goto L11; /* no new isomorphism found */
    4350                 :             :     }
    4351                 :             : 
    4352                 :             :     /*  Output gamma (it is the Aut(G) generator) -- omitted -- */
    4353                 :          73 :     nNumFoundGenerators++;
    4354                 :             :     /* if ( tvc in mcr(theta) ) goto L11; */
    4355         [ +  - ]:          73 :     if (tvc == GetUnorderedPartitionMcrNode( &theta, tvc ))
    4356                 :             :     {
    4357                 :          73 :         goto L11;
    4358                 :             :     }
    4359                 :           0 :     k = h_zeta;
    4360                 :           0 :     goto L13;
    4361                 :             : 
    4362                 :          73 : L11:
    4363         [ +  - ]:          73 :     k = lab ? h_rho : h_zeta; /***Changed*** originally was k = h_rho; */
    4364                 :             : 
    4365                 :          73 : L12:
    4366                 :             :     /* if ( e[k-1] == 1 ) */
    4367                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    4368                 :             :     if (e[k - 1] == 1 && v[k - 1] == INCHI_CANON_INFINITY)
    4369                 :             :     {
    4370                 :             :         int stop = 1;          /* <BRKPT> testing only */
    4371                 :             :     }
    4372                 :             : #endif
    4373   [ +  -  -  - ]:          73 :     if (e[k - 1] == 1 && v[k - 1] != INCHI_CANON_INFINITY)
    4374                 :             :     {
    4375                 :             :         /* INCHI_CANON_INFINITY for testing only */
    4376                 :           0 :         CellIntersectWithSet( pCG, &pi[k - 1], &W[k - 1], &Omega, l );
    4377                 :             :     }
    4378                 :             : 
    4379                 :         145 : L13:
    4380                 :             : 
    4381   [ -  +  -  - ]:         177 :     if ((UserAction && USER_ACTION_QUIT == ( *UserAction )( )) ||
    4382   [ -  +  -  - ]:         177 :          (ConsoleQuit && ( *ConsoleQuit )( ))) /* djb-rwth: addressing LLVM warning */
    4383                 :             :     {
    4384                 :           0 :         ret = CT_USER_QUIT_ERR;
    4385                 :           0 :         goto exit_error;
    4386                 :             :     }
    4387                 :             : 
    4388         [ -  + ]:         177 :     if (bInchiTimeIsOver( ic, pCD->ulTimeOutTime ))
    4389                 :             :     {
    4390                 :           0 :         ret = CT_TIMEOUT_ERR;
    4391                 :           0 :         goto exit_error;
    4392                 :             :     }
    4393                 :             : 
    4394         [ +  + ]:         177 :     if (k == 0)
    4395                 :             :     {
    4396                 :          32 :         goto exit_function; /* stop */
    4397                 :             :     }
    4398                 :             : 
    4399   [ +  -  +  + ]:         145 :     if (lab && k < h_rho)
    4400                 :             :     {
    4401                 :             :         /***Added***/
    4402                 :          72 :         h_rho = k;
    4403                 :             :     }
    4404                 :             : 
    4405         [ -  + ]:         145 :     if (k > h_zeta)
    4406                 :             :     {
    4407         [ #  # ]:           0 :         if (v[k - 1] == INCHI_CANON_INFINITY)
    4408                 :             :         {
    4409                 :             :             /*** Added by DCh for testing only ****/
    4410                 :           0 :             k--;
    4411                 :           0 :             goto L13;
    4412                 :             :         }
    4413                 :           0 :         goto L17;
    4414                 :             :     }
    4415         [ +  + ]:         145 :     if (k == h_zeta)
    4416                 :             :     {
    4417                 :          73 :         goto L14;
    4418                 :             :     }
    4419                 :          72 :     h_zeta = k;
    4420                 :          72 :     tvc = tvh = CellGetMinNode( &pi[k - 1], &W[k - 1], 0, pCD1 );
    4421                 :             : 
    4422                 :         145 : L14:
    4423                 :             :     /* if v[k] and tvh are in the same cell of theta then index ++ */
    4424         [ +  - ]:         352 :     if (GetUnorderedPartitionMcrNode( &theta, v[k - 1] ) ==
    4425                 :         176 :          GetUnorderedPartitionMcrNode( &theta, tvh ))
    4426                 :             :     {
    4427                 :         176 :         index++;
    4428                 :             :     }
    4429                 :         176 :     v[k - 1] = CellGetMinNode( &pi[k - 1], &W[k - 1], v[k - 1], pCD1 );
    4430                 :             : 
    4431         [ +  + ]:         176 :     if (v[k - 1] == INCHI_CANON_INFINITY)
    4432                 :             :     {
    4433                 :          72 :         goto L16;
    4434                 :             :     }
    4435         [ +  + ]:         104 :     if (v[k - 1] != GetUnorderedPartitionMcrNode( &theta, v[k - 1] ))
    4436                 :             :     {
    4437                 :          31 :         goto L14;
    4438                 :             :     }
    4439                 :             : 
    4440                 :          73 : L15:
    4441         [ +  + ]:          73 :     t_Lemma = inchi_min( t_Lemma, k + 1 );
    4442                 :          73 :     hz_zeta = inchi_min( hz_zeta, k );
    4443                 :             :     /*
    4444                 :             :     if ( lab && hz_rho >= k ) {
    4445                 :             :         hz_rho = k;
    4446                 :             :         qzb_rho = 0;
    4447                 :             :     }
    4448                 :             :     */
    4449         [ +  - ]:          73 :     if (lab)
    4450                 :             :     {
    4451         [ +  - ]:          73 :         if (hz_rho >= k /*-1*/)
    4452                 :             :         {
    4453                 :          73 :             qzb_rho = 0;
    4454                 :             :         }
    4455         [ +  - ]:          73 :         if (hz_rho > k)
    4456                 :             :         {
    4457                 :          73 :             hz_rho = k;
    4458                 :             :         }
    4459                 :          73 :         UpdateCompareLayers( kLeast_rho, hz_rho );
    4460                 :             :     }
    4461         [ +  + ]:          73 :     if (pzb_rho_fix)
    4462                 :             :     {
    4463         [ +  - ]:          21 :         if (hzb_rho_fix >= k /*-1*/)
    4464                 :             :         {
    4465                 :          21 :             qzb_rho_fix = 0;
    4466                 :             :         }
    4467         [ +  - ]:          21 :         if (hzb_rho_fix > k)
    4468                 :             :         {
    4469                 :          21 :             hzb_rho_fix = k;
    4470                 :             :         }
    4471                 :          21 :         UpdateCompareLayers( kLeast_rho_fix, hzb_rho_fix );
    4472                 :             :     }
    4473                 :             : 
    4474                 :          73 :     goto L2;
    4475                 :             : 
    4476                 :          72 : L16:
    4477   [ +  -  +  - ]:          72 :     if (t_eq_zeta == k + 1 && index == CellGetNumberOfNodes( &pi[k - 1], &W[k - 1] ))
    4478                 :             :     {
    4479                 :          72 :         t_eq_zeta = k;
    4480                 :             :     }
    4481                 :             : 
    4482                 :          72 :     size *= (double) index;
    4483                 :             :     /******************** <<<===== A **************************/
    4484                 :             :     /* passed K times after passing point A. At these passes
    4485                 :             :        k = K, K-1, ..., 1 in this order
    4486                 :             :     */
    4487                 :          72 :     index = 0;
    4488                 :          72 :     k--;
    4489                 :          72 :     goto L13;
    4490                 :             : 
    4491                 :           0 : L17:
    4492                 :             :     /* if ( e[k-1] == 0 ) */
    4493                 :             : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    4494                 :             :     if (e[k - 1] == 0 && v[k - 1] == INCHI_CANON_INFINITY)
    4495                 :             :     {
    4496                 :             :         /* testing only */
    4497                 :             :         int stop = 1;  /* <BRKPT> */
    4498                 :             :     }
    4499                 :             : #endif
    4500                 :             :     /*
    4501                 :             :     if ( e[k] == 0 set W[k] = Intersection(W[k], Omega[i]) for each i = 1..l,
    4502                 :             :          such that {v[1]..v[k-1]} in Phi[i]
    4503                 :             :     */
    4504   [ #  #  #  # ]:           0 :     if (e[k - 1] == 0 && v[k - 1] != INCHI_CANON_INFINITY) /* Added v[k-1]!=... DCh */
    4505                 :             :     {
    4506                 :           0 :         NodeSetFromVertices( pCG, &cur_nodes, 1, v, k - 1 );
    4507         [ #  # ]:           0 :         for (i = 1; i <= l; i++)
    4508                 :             :         {
    4509         [ #  # ]:           0 :             if (AllNodesAreInSet( &cur_nodes, 1, &Phi, i ))
    4510                 :             :             {
    4511                 :           0 :                 CellIntersectWithSet( pCG, &pi[k - 1], &W[k - 1], &Omega, i );
    4512                 :             :             }
    4513                 :             :         }
    4514                 :             :     }
    4515                 :             : 
    4516                 :           0 :     e[k - 1] = 1;
    4517                 :           0 :     v[k - 1] = CellGetMinNode( &pi[k - 1], &W[k - 1], v[k - 1], pCD1 );
    4518         [ #  # ]:           0 :     if (v[k - 1] != INCHI_CANON_INFINITY)
    4519                 :             :     {
    4520                 :           0 :         goto L15;
    4521                 :             :     }
    4522                 :           0 :     k--;
    4523                 :           0 :     goto L13;
    4524                 :             : /* L18: see above */
    4525                 :             : 
    4526                 :         175 : exit_function:
    4527                 :             :     /* CtPartFill( G, pCD, &rho, pzb_rho, 1, n, n_tg ); */
    4528         [ -  + ]:         175 :     if (!bRhoIsDiscrete)
    4529                 :             :     {
    4530                 :           0 :         ret = CT_CANON_ERR;
    4531                 :           0 :         goto exit_error;
    4532                 :             :     }
    4533                 :             : 
    4534         [ +  + ]:         175 :     if (pzb_rho_fix)
    4535                 :             :     {
    4536                 :          14 :         qzb_rho_fix = CtFullCompare( pzb_rho_fix, pzb_rho, 1, bSplitTautCompare );
    4537         [ -  + ]:          14 :         if (qzb_rho_fix)
    4538                 :             :         {
    4539                 :           0 :             ret = CT_CANON_ERR;
    4540                 :           0 :             goto exit_error;
    4541                 :             :         }
    4542                 :             :     }
    4543                 :             : 
    4544                 :             :     /* SymmRank */
    4545                 :         175 :     memset( nSymmRank, 0, n_tg * sizeof( nSymmRank[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4546         [ +  + ]:        1048 :     for (i = 0; i < n_tg; i++)
    4547                 :             :     {
    4548                 :         873 :         k = rho.AtNumber[i];
    4549                 :         873 :         k2 = (int) GetUnorderedPartitionMcrNode( &theta, (AT_NUMB) ( k + 1 ) ) - 1;
    4550   [ +  +  -  + ]:         873 :         if (!nSymmRank[k2] || nSymmRank[k2] > rho.Rank[k])
    4551                 :             :         {
    4552                 :         743 :             nSymmRank[k2] = rho.Rank[k];
    4553                 :             :         }
    4554                 :             :     }
    4555         [ +  + ]:        1048 :     for (i = 0; i < n_tg; i++)
    4556                 :             :     {
    4557                 :         873 :         k = rho.AtNumber[i];
    4558                 :         873 :         k2 = (int) GetUnorderedPartitionMcrNode( &theta, (AT_NUMB) ( k + 1 ) ) - 1;
    4559                 :         873 :         nSymmRank[k] = nSymmRank[k2];
    4560                 :             :     }
    4561                 :             :     /* CanonRank, nAtomNumberCanon */
    4562                 :         175 :     memcpy(nCanonRank, rho.Rank, n_tg * sizeof(nCanonRank[0]));
    4563                 :         175 :     memcpy(nAtomNumberCanon, rho.AtNumber, n_tg * sizeof(nAtomNumberCanon[0]));
    4564                 :             :     /* LinearCT */
    4565         [ +  - ]:         175 :     if (pzb_rho)
    4566                 :             :     {
    4567                 :         175 :         *nLenCt = pzb_rho->lenCt - 1;
    4568                 :             :     }
    4569   [ -  +  -  -  :         175 :     if (pCt && pzb_rho && (*nLenCt > 0)) /* djb-rwth: GHI #164 fix */
                   -  - ]
    4570                 :             :     {
    4571                 :           0 :         memcpy(pCt, pzb_rho->Ctbl, *nLenCt * sizeof(pCt[0]));
    4572                 :             :     }
    4573                 :         175 :     pCC->lNumTotCT = pCC->lNumDecreasedCT + pCC->lNumRejectedCT + pCC->lNumEqualCT;
    4574                 :         175 :     pCC->dGroupSize = size;
    4575                 :         175 :     pCC->lNumGenerators = nNumFoundGenerators;
    4576                 :         175 :     pCC->lNumStoredIsomorphisms = l;
    4577                 :             :     /* Note: check nNumFoundGenerators */
    4578                 :             : 
    4579   [ -  +  -  + ]:         175 :     if (pp_zb_rho_out && !*pp_zb_rho_out)
    4580                 :             :     {
    4581                 :         175 :         *pp_zb_rho_out = pzb_rho;
    4582                 :         175 :         pzb_rho = NULL;
    4583                 :             :     }
    4584                 :             : 
    4585                 :             : 
    4586                 :             : 
    4587                 :           0 : exit_error:
    4588                 :             :     INCHI_HEAPCHK
    4589                 :             : 
    4590                 :         175 :     UnorderedPartitionFree( &theta );
    4591                 :         175 :     UnorderedPartitionFree( &theta_from_gamma );
    4592         [ +  - ]:         175 :     if (W)
    4593                 :             :     {
    4594         [ +  - ]:         175 :         inchi_free( W );
    4595                 :             :     }
    4596         [ +  - ]:         175 :     if (v)
    4597                 :             :     {
    4598         [ +  - ]:         175 :         inchi_free( v );
    4599                 :             :     }
    4600         [ +  - ]:         175 :     if (e)
    4601                 :             :     {
    4602         [ +  - ]:         175 :         inchi_free( e );
    4603                 :             :     }
    4604         [ -  + ]:         175 :     if (qzb)
    4605                 :             :     {
    4606         [ #  # ]:           0 :         inchi_free( qzb );
    4607                 :             :     }
    4608                 :         175 :     CTableFree( &Lambda );
    4609                 :         175 :     CTableFree( &zf_zeta );
    4610         [ -  + ]:         175 :     if (pzb_rho)
    4611                 :             :     {
    4612                 :           0 :         CTableFree( pzb_rho );
    4613         [ #  # ]:           0 :         inchi_free( pzb_rho );
    4614                 :           0 :         pzb_rho = NULL;
    4615                 :             :     }
    4616                 :             :     /* CTableFree( &zf_zeta2 ); */
    4617                 :         175 :     NodeSetFree( pCG, &Omega );
    4618                 :         175 :     NodeSetFree( pCG, &Phi );
    4619                 :             :     /* NodeSetFree( &mcr_theta, n, 1 ); */
    4620                 :         175 :     NodeSetFree( pCG, &cur_nodes );
    4621                 :         175 :     PartitionFree( &zeta );
    4622                 :             :     /* PartitionFree( &zeta2 ); */
    4623                 :         175 :     PartitionFree( &rho );
    4624                 :         175 :     TranspositionFree( &gamma );
    4625                 :             : 
    4626                 :         175 :     return ret;
    4627                 :             : }
    4628                 :             : 
    4629                 :             : 
    4630                 :             : /****************************************************************************
    4631                 :             :  SetInitialRanks2: Set initial ranks in nRank according to
    4632                 :             :                    pAtomInvariant[] values
    4633                 :             :                    Make sure enough prines have been generated.
    4634                 :             : ****************************************************************************/
    4635                 :             : /* Upon exit: */
    4636                 :             : /* nAtomNumber[i]: number (from 0) of an atom in the ith (from 0) position of the sorted order */
    4637                 :             : /* nNewRank[i]:    initial rank of the atom[i] based on atom invariants; from 1 to num_atoms */
    4638                 :             : /* Return value:   Number of different ranks */
    4639                 :         189 : int SetInitialRanks2( int num_atoms,
    4640                 :             :                       ATOM_INVARIANT2* pAtomInvariant2,
    4641                 :             :                       AT_RANK *nNewRank,
    4642                 :             :                       AT_RANK *nAtomNumber,
    4643                 :             :                       CANON_GLOBALS *pCG )
    4644                 :             : {
    4645                 :             :     int i, nNumDiffRanks;
    4646                 :             :     AT_RANK nCurrentRank;
    4647                 :             : 
    4648         [ +  + ]:        1125 :     for (i = 0; i < num_atoms; i++)
    4649                 :             :     {
    4650                 :         936 :         nAtomNumber[i] = (AT_RANK) i;
    4651                 :             :     }
    4652                 :             : 
    4653                 :             :     /* global for qsort */
    4654                 :         189 :     pCG->m_pAtomInvariant2ForSort = pAtomInvariant2;
    4655                 :             : 
    4656                 :         189 :     inchi_qsort( pCG, nAtomNumber, num_atoms, sizeof( nAtomNumber[0] ), CompAtomInvariants2 );
    4657                 :             : 
    4658                 :             :     /* nNewRank[i]: non-decreading order; do not increment nCurrentRank */
    4659                 :             :     /*           if consecutive sorted atom invariants are identical */
    4660                 :             : 
    4661                 :             :     /* djb-rwth: fixing oss-fuzz issue #69315 */
    4662                 :         189 :     nNumDiffRanks = 1;
    4663         [ +  - ]:         189 :     if (num_atoms > 0)
    4664                 :             :     {
    4665                 :         189 :         nCurrentRank = (AT_RANK)num_atoms;
    4666                 :         189 :         nNewRank[nAtomNumber[num_atoms - 1]] = nCurrentRank;
    4667         [ +  + ]:         936 :         for (i = num_atoms - 1; i > 0; i--)
    4668                 :             :         {
    4669                 :             :             /* Note: CompAtomInvariants2Only() in following line implicitly reads pAtomInvariant2 pointed by pAtomInvariant2ForSort */
    4670         [ +  + ]:         747 :             if (CompAtomInvariants2Only(&nAtomNumber[i - 1], &nAtomNumber[i], pCG))
    4671                 :             :             {
    4672                 :         243 :                 nNumDiffRanks++;
    4673                 :         243 :                 nCurrentRank = (AT_RANK)i;
    4674                 :             :             }
    4675                 :         747 :             nNewRank[nAtomNumber[i - 1]] = nCurrentRank;
    4676                 :             :         }
    4677                 :             :     }
    4678                 :             : 
    4679                 :         189 :     return nNumDiffRanks;
    4680                 :             : }
    4681                 :             : 
    4682                 :             : 
    4683                 :             : /****************************************************************************/
    4684                 :         175 : void FillOutAtomInvariant2( sp_ATOM* at,
    4685                 :             :                             int num_atoms,
    4686                 :             :                             int num_at_tg,
    4687                 :             :                             ATOM_INVARIANT2* pAtomInvariant,
    4688                 :             :                             int bIgnoreIsotopic,
    4689                 :             :                             int bHydrogensInRanks,
    4690                 :             :                             int bHydrogensFixedInRanks,
    4691                 :             :                             int bDigraph,
    4692                 :             :                             int bTautGroupsOnly,
    4693                 :             :                             T_GROUP_INFO *t_group_info )
    4694                 :             : {
    4695                 :             :     int i, k, j, i_t_group;
    4696                 :             :     /* tautomers */
    4697                 :         175 :     T_GROUP          *t_group = NULL;
    4698                 :         175 :     int               num_t_groups = 0;
    4699                 :         175 :     int               num_tautomer_iso = 0;
    4700                 :             : #define ELEM_NAME_LEN  2
    4701                 :             :     char ChemElements[ELEM_NAME_LEN*NUM_CHEM_ELEMENTS + ELEM_NAME_LEN];
    4702                 :             :     char CurElement[ELEM_NAME_LEN + ELEM_NAME_LEN], *pCurElem;
    4703                 :         175 :     int  nNumChemElements = 0;
    4704                 :         175 :     int  nNumHydrogenAtoms = 0;
    4705                 :         175 :     int  nNumCarbonAtoms = 0;
    4706                 :             :     
    4707                 :         175 :     ChemElements[0] = '\0'; /* djb-rwth: initialisation prevents empty string comparison */
    4708                 :         175 :     memset( ChemElements, 0, sizeof( ChemElements ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4709                 :         175 :     memset( CurElement, 0, sizeof( CurElement ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4710                 :         175 :     nNumChemElements = 0;
    4711                 :             : 
    4712   [ +  +  +  - ]:         175 :     if (num_at_tg > num_atoms && t_group_info)
    4713                 :             :     {
    4714                 :           7 :         t_group = t_group_info->t_group;
    4715                 :           7 :         num_t_groups = t_group_info->num_t_groups;
    4716         [ +  - ]:           7 :         num_tautomer_iso = t_group_info->bIgnoreIsotopic ? 0 : T_NUM_ISOTOPIC;
    4717                 :             :     }
    4718                 :             : 
    4719         [ +  + ]:         175 :     if (!bTautGroupsOnly)
    4720                 :             :     {
    4721                 :             : 
    4722         [ +  + ]:         971 :         for (i = 0; i < num_atoms; i++)
    4723                 :             :         {
    4724         [ +  + ]:         810 :             if (!strcmp( at[i].elname, "C" ))
    4725                 :             :             {
    4726                 :         471 :                 nNumCarbonAtoms++;
    4727                 :             :             }
    4728         [ +  + ]:         339 :             else if (!strcmp( at[i].elname, "H" ) ||
    4729         [ +  - ]:         333 :                  !strcmp( at[i].elname, "D" ) ||
    4730         [ -  + ]:         333 :                  !strcmp( at[i].elname, "T" ))
    4731                 :             :             {
    4732                 :           6 :                 nNumHydrogenAtoms++;
    4733                 :             :             }
    4734                 :             :             else
    4735                 :             :             {
    4736                 :         333 :                 CurElement[0] = at[i].elname[0];
    4737         [ +  + ]:         333 :                 CurElement[1] = at[i].elname[1] ? at[i].elname[1] : ' ';
    4738         [ +  + ]:         333 :                 if (!( pCurElem = strstr( ChemElements, CurElement ) )) /* djb-rwth: ignoring LLVM warning: variable used for function return value */
    4739                 :             :                 {
    4740                 :         193 :                     strcat(ChemElements, CurElement);
    4741                 :         193 :                     nNumChemElements++;
    4742                 :             :                 }
    4743                 :             :             }
    4744                 :             :         }
    4745         [ +  + ]:         161 :         if (nNumChemElements > 1)
    4746                 :             :         {
    4747                 :          41 :             qsort( ChemElements, nNumChemElements, ELEM_NAME_LEN, CompChemElemLex );
    4748                 :             :         }
    4749         [ +  + ]:         161 :         if (nNumCarbonAtoms)
    4750                 :             :         {
    4751         [ +  + ]:          73 :             if (nNumChemElements)
    4752                 :             :             {
    4753                 :          62 :                 memmove(ChemElements + ELEM_NAME_LEN, ChemElements, (long long)ELEM_NAME_LEN * (long long)nNumChemElements); /* djb-rwth: cast operators added */
    4754                 :             :             }
    4755                 :          73 :             ChemElements[0] = 'C';
    4756                 :          73 :             ChemElements[1] = ' ';
    4757                 :          73 :             nNumChemElements++;
    4758                 :             :         }
    4759         [ +  + ]:         161 :         if (nNumHydrogenAtoms)
    4760                 :             :         {
    4761                 :           6 :             ChemElements[ELEM_NAME_LEN*nNumChemElements] = 'H';
    4762                 :           6 :             ChemElements[ELEM_NAME_LEN*nNumChemElements + 1] = ' ';
    4763                 :           6 :             nNumChemElements++;
    4764                 :             :         }
    4765                 :             : 
    4766                 :             :         /* general */
    4767         [ +  + ]:         971 :         for (i = 0; i < num_atoms; i++)
    4768                 :             :         {
    4769                 :         810 :             memset( &pAtomInvariant[i], 0, sizeof( pAtomInvariant[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4770                 :         810 :             CurElement[0] = at[i].elname[0];
    4771         [ +  + ]:         810 :             CurElement[1] = at[i].elname[1] ? at[i].elname[1] : ' ';
    4772                 :         810 :             pCurElem = strstr( ChemElements, CurElement );
    4773         [ +  - ]:         810 :             if (pCurElem)
    4774                 :             :             {
    4775                 :         810 :                 j = (int) ( pCurElem - ChemElements ) / ELEM_NAME_LEN + 1;
    4776                 :             :             }
    4777                 :             :             else
    4778                 :             :             {
    4779                 :           0 :                 j = nNumChemElements; /* must be D or T */
    4780                 :             :             }
    4781                 :             :             /* at[i].hill_type = (U_CHAR) j; */
    4782                 :         810 :             pAtomInvariant[i].val[AT_INV_HILL_ORDER] = j;
    4783                 :             : 
    4784                 :         810 :             pAtomInvariant[i].val[AT_INV_NUM_CONNECTIONS] = at[i].valence;
    4785         [ -  + ]:         810 :             if (bHydrogensInRanks)
    4786                 :             :             {
    4787   [ #  #  #  # ]:           0 :                 pAtomInvariant[i].val[AT_INV_NUM_H] = ( ( t_group && at[i].endpoint > 0 ) ? 0 : at[i].num_H );
    4788                 :             :             }
    4789         [ -  + ]:         810 :             if (bHydrogensFixedInRanks)
    4790                 :             :             {
    4791   [ #  #  #  # ]:           0 :                 pAtomInvariant[i].val[AT_INV_NUM_H_FIX] = ( ( t_group && at[i].endpoint > 0 ) ? at[i].num_H : 0 );
    4792                 :             :             }
    4793   [ +  -  -  +  :         810 :             if (!bDigraph &&  t_group && ( i_t_group = (int) at[i].endpoint - 1 ) >= 0 && i_t_group < num_t_groups)
             -  -  -  - ]
    4794                 :             :             {
    4795                 :           0 :                 pAtomInvariant[i].val[AT_INV_NUM_TG_ENDPOINTS] = t_group[i_t_group].nNumEndpoints;
    4796         [ #  # ]:           0 :                 for (j = 0; j < T_NUM_NO_ISOTOPIC; j++)
    4797                 :             :                 {
    4798                 :           0 :                     pAtomInvariant[i].val[AT_INV_TG_NUMBERS + j] = t_group[i_t_group].num[j];
    4799                 :             :                 }
    4800         [ #  # ]:           0 :                 for (j = 0; j < num_tautomer_iso; j++)
    4801                 :             :                 {
    4802                 :           0 :                     pAtomInvariant[i].val[AT_INV_TAUT_ISO + j] = t_group[i_t_group].num[j + T_NUM_NO_ISOTOPIC];
    4803                 :             :                 }
    4804                 :             :             }
    4805         [ -  + ]:         810 :             pAtomInvariant[i].iso_sort_key = bIgnoreIsotopic ? 0 : at[i].iso_sort_key;
    4806                 :             :         }
    4807                 :             :     }
    4808                 :             :     else
    4809                 :             :     {
    4810                 :             :         /* fill tautomeric groups only */
    4811                 :          14 :         memset( pAtomInvariant, 0, num_at_tg * sizeof( pAtomInvariant[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4812                 :             :     }
    4813                 :             : 
    4814                 :             :     /**************************************/
    4815                 :             :     /*          tautomeric groups         */
    4816                 :             :     /**************************************/
    4817         [ +  + ]:         187 :     for (i = num_atoms; i < num_at_tg; i++)
    4818                 :             :     {
    4819                 :             : 
    4820                 :          12 :         k = i - num_atoms;
    4821                 :          12 :         memset( &pAtomInvariant[i], 0, sizeof( pAtomInvariant[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4822         [ -  + ]:          12 :         if (!t_group)
    4823                 :           0 :             continue;
    4824                 :             :         /* make sure ranks of t-groups are larger than that of any atom */
    4825                 :             :          /* greater than for any real atom */
    4826         [ -  + ]:          12 :         pAtomInvariant[i].val[AT_INV_HILL_ORDER] = bTautGroupsOnly ? num_at_tg : nNumChemElements + 1;
    4827                 :             :         /* greater than for any real atom */
    4828                 :          12 :         pAtomInvariant[i].val[AT_INV_NUM_CONNECTIONS] = MAXVAL + 1;
    4829         [ +  - ]:          12 :         if (k < num_t_groups)
    4830                 :             :         {
    4831                 :          12 :             pAtomInvariant[i].val[AT_INV_NUM_TG_ENDPOINTS] = t_group[k].nNumEndpoints;
    4832         [ +  + ]:          36 :             for (j = 0; j < T_NUM_NO_ISOTOPIC; j++)
    4833                 :             :             {
    4834                 :          24 :                 pAtomInvariant[i].val[AT_INV_TAUT_ISO + j] = t_group[k].num[j];
    4835                 :             :             }
    4836         [ -  + ]:          12 :             for (j = 0; j < num_tautomer_iso; j++)
    4837                 :             :             {
    4838                 :           0 :                 pAtomInvariant[i].val[AT_INV_TAUT_ISO + j] = t_group[k].num[j + T_NUM_NO_ISOTOPIC];
    4839                 :             :             }
    4840                 :             :         }
    4841                 :             :     }
    4842                 :         175 : }
    4843                 :             : 
    4844                 :             : 
    4845                 :             : /*****************************************************************************/
    4846                 :         616 : void CleanNumH( NUM_H *NumH, int len )
    4847                 :             : {
    4848                 :             :     int i;
    4849         [ +  + ]:         616 :     if (NumH)
    4850                 :             :     {
    4851         [ +  + ]:        2312 :         for (i = 0; i < len; i++)
    4852                 :             :         {
    4853         [ +  + ]:        1990 :             if (NumH[i] == EMPTY_H_NUMBER)
    4854                 :             :             {
    4855                 :         556 :                 NumH[i] = 0;
    4856                 :             :             }
    4857                 :             :             else
    4858                 :             :             {
    4859                 :        1434 :                 NumH[i] -= BASE_H_NUMBER;
    4860                 :             :             }
    4861                 :             :         }
    4862                 :             :     }
    4863                 :         616 : }
    4864                 :             : 
    4865                 :             : 
    4866                 :             : /****************************************************************************/
    4867                 :         161 : int CleanCt( AT_RANK *Ct, int len )
    4868                 :             : {
    4869   [ +  -  +  - ]:         161 :     if (Ct && Ct[len] == EMPTY_CT)
    4870                 :             :     {
    4871                 :         161 :         Ct[len] = 0;
    4872                 :         161 :         return 1;
    4873                 :             :     }
    4874                 :             : 
    4875                 :           0 :     return 0;
    4876                 :             : }
    4877                 :             : 
    4878                 :             : 
    4879                 :             : /*****************************************************************************/
    4880                 :           0 : void CleanIsoSortKeys( AT_ISO_SORT_KEY * isk, int len )
    4881                 :             : {
    4882                 :             :     int i;
    4883         [ #  # ]:           0 :     if (isk)
    4884                 :             :     {
    4885         [ #  # ]:           0 :         for (i = 0; i < len; i++)
    4886                 :             :         {
    4887         [ #  # ]:           0 :             if (isk[i] == EMPTY_ISO_SORT_KEY)
    4888                 :             :             {
    4889                 :           0 :                 isk[i] = 0;
    4890                 :             :             }
    4891                 :             :         }
    4892                 :             :     }
    4893                 :           0 : }
    4894                 :             : 
    4895                 :             : 
    4896                 :             : /*****************************************************************************/
    4897                 :             : 
    4898                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    4899                 :             : void MergeCleanIsoSortKeys( AT_ISO_SORT_KEY * isk1, AT_ISO_SORT_KEY * isk2, int len )
    4900                 :             : {
    4901                 :             :     int i;
    4902                 :             :     AT_ISO_SORT_KEY k1, k2;
    4903                 :             :     if (isk1 && isk2)
    4904                 :             :     {
    4905                 :             :         for (i = 0; i < len; i++)
    4906                 :             :         {
    4907                 :             :             k1 = ( isk1[i] == EMPTY_ISO_SORT_KEY ) ? 0 : isk1[i];
    4908                 :             :             k2 = ( isk2[i] == EMPTY_ISO_SORT_KEY ) ? 0 : isk2[i];
    4909                 :             :             isk1[i] = k1 | k2;
    4910                 :             :         }
    4911                 :             :     }
    4912                 :             :     else if (isk1)
    4913                 :             :     {
    4914                 :             :         CleanIsoSortKeys( isk1, len );
    4915                 :             :     }
    4916                 :             : }
    4917                 :             : #endif
    4918                 :             : 
    4919                 :             : 
    4920                 :             : #define FREE_CONTABLE( X) if (X) {CTableFree( X);inchi_free( X);}
    4921                 :             : #define FREE_ARRAY( X) if (X) inchi_free( X);
    4922                 :             : 
    4923                 :             : 
    4924                 :             : /****************************************************************************/
    4925                 :         161 : void DeAllocBCN( BCN *pBCN )
    4926                 :             : {
    4927                 :             :     int    i, k;
    4928                 :             :     FTCN  *ftcn;
    4929         [ -  + ]:         161 :     if (!pBCN)
    4930                 :             :     {
    4931                 :           0 :         return;
    4932                 :             :     }
    4933         [ +  - ]:         161 :     if (pBCN->pRankStack)
    4934                 :             :     {
    4935         [ +  + ]:        1671 :         for (i = 0; i < pBCN->nMaxLenRankStack; i++)
    4936                 :             :         {
    4937   [ +  +  +  - ]:        1510 :             FREE_ARRAY( pBCN->pRankStack[i] )
    4938                 :             :         }
    4939   [ +  -  +  - ]:         161 :         FREE_ARRAY( pBCN->pRankStack )
    4940                 :             :     }
    4941         [ +  + ]:         483 :     for (k = 0; k < TAUT_NUM; k++)
    4942                 :             :     {
    4943                 :         322 :         ftcn = pBCN->ftcn + k;
    4944                 :         322 :         FreeNeighList( ftcn->NeighList );
    4945                 :             : 
    4946   [ +  +  +  - ]:         322 :         FREE_ARRAY( ftcn->LinearCt )
    4947                 :             : 
    4948                 :         322 :         PartitionFree( &ftcn->PartitionCt );
    4949                 :             : 
    4950   [ +  +  +  - ]:         322 :         FREE_ARRAY( ftcn->nSymmRankCt )
    4951   [ +  +  +  - ]:         322 :         FREE_ARRAY( ftcn->nNumHOrig )
    4952   [ +  +  +  - ]:         322 :         FREE_ARRAY( ftcn->nNumH )
    4953   [ -  +  -  - ]:         322 :         FREE_ARRAY( ftcn->nNumHOrigFixH )
    4954   [ -  +  -  - ]:         322 :         FREE_ARRAY( ftcn->nNumHFixH )
    4955                 :             : 
    4956                 :         322 :         PartitionFree( &ftcn->PartitionCtIso );
    4957                 :             : 
    4958   [ -  +  -  - ]:         322 :         FREE_ARRAY( ftcn->nSymmRankCtIso )
    4959   [ -  +  -  - ]:         322 :         FREE_ARRAY( ftcn->iso_sort_keys )
    4960   [ -  +  -  - ]:         322 :         FREE_ARRAY( ftcn->iso_sort_keysOrig )
    4961   [ -  +  -  - ]:         322 :         FREE_ARRAY( ftcn->iso_exchg_atnos )
    4962   [ -  +  -  - ]:         322 :         FREE_ARRAY( ftcn->iso_exchg_atnosOrig )
    4963                 :             :     }
    4964                 :             : }
    4965                 :             : 
    4966                 :             : #undef FREE_CONTABLE
    4967                 :             : #undef FREE_ARRAY
    4968                 :             : 
    4969                 :             : 
    4970                 :             : #if ( bRELEASE_VERSION == 0 && FIND_CANON_NE_EQUITABLE == 1 )
    4971                 :             : 
    4972                 :             : /****************************************************************************
    4973                 :             :  debug: find whether canonical equivalence is
    4974                 :             :  different from equitable partition
    4975                 :             : ****************************************************************************/
    4976                 :             : int bCanonIsFinerThanEquitablePartition( int num_atoms,
    4977                 :             :                                          sp_ATOM* at,
    4978                 :             :                                          AT_RANK *nSymmRank )
    4979                 :             : {
    4980                 :             :     AT_RANK *nRank = NULL;
    4981                 :             :     AT_RANK *nAtomNumber = NULL;
    4982                 :             :     AT_RANK *nTempRank = NULL;
    4983                 :             :     AT_RANK nCurSymm, nCurRank;
    4984                 :             :     ATOM_INVARIANT2 *pAtomInvariant = NULL;
    4985                 :             :     NEIGH_LIST      *NeighList = NULL;
    4986                 :             : 
    4987                 :             :     int              nNumCurrRanks, i, is, ir, j;
    4988                 :             :     long             lCount;
    4989                 :             :     int              bIsNotSame = 0;
    4990                 :             : 
    4991                 :             :     if (at && nSymmRank)
    4992                 :             :     {
    4993                 :             :         if (!( nRank = (AT_RANK*) inchi_calloc( num_atoms, sizeof( nRank[0] ) ) ) ||
    4994                 :             :              !( nAtomNumber = (AT_RANK*) inchi_calloc( num_atoms, sizeof( nAtomNumber[0] ) ) ) ||
    4995                 :             :              !( nTempRank = (AT_RANK*) inchi_calloc( num_atoms, sizeof( nTempRank[0] ) ) ) ||
    4996                 :             :              !( pAtomInvariant = (ATOM_INVARIANT2 *) inchi_calloc( num_atoms, sizeof( pAtomInvariant[0] ) ) )
    4997                 :             :             )
    4998                 :             :         {
    4999                 :             :             goto exit_err;
    5000                 :             :         }
    5001                 :             :         if (!( NeighList = CreateNeighList( num_atoms, num_atoms, at, 0, NULL ) ))
    5002                 :             :         {
    5003                 :             :             goto exit_err;
    5004                 :             :         }
    5005                 :             : 
    5006                 :             :         FillOutAtomInvariant2( at,
    5007                 :             :                                num_atoms,
    5008                 :             :                                num_atoms,
    5009                 :             :                                pAtomInvariant,
    5010                 :             :                                1 /*bIgnoreIsotopic*/,
    5011                 :             :                                1 /*bHydrogensInRanks*/,
    5012                 :             :                                1 /*bHydrogensFixedInRanks*/,
    5013                 :             :                                0 /*bTaut=bDigraph*/,
    5014                 :             :                                0 /* bTautGroupsOnly */,
    5015                 :             :                                NULL /*t_group_info*/ );
    5016                 :             : 
    5017                 :             :         /* initial partitioning of a hydrogenless skeleton: create equitable partition (assign initial ranks) */
    5018                 :             :         nNumCurrRanks = SetInitialRanks2( num_atoms, pAtomInvariant, nRank, nAtomNumber, pCG );
    5019                 :             : 
    5020                 :             :         lCount = 0;
    5021                 :             :         /* make equitable partition in pBCN->pRankStack[0,1] */
    5022                 :             :         nNumCurrRanks = DifferentiateRanks2( pCG, num_atoms, NeighList,
    5023                 :             :                                             nNumCurrRanks, nRank,
    5024                 :             :                                             nTempRank, nAtomNumber, &lCount, 0 /* 0 means use qsort */ );
    5025                 :             : 
    5026                 :             : 
    5027                 :             :         /* at this point the equitable partition is in nRank; the order of atoms is in nAtomNumber*/
    5028                 :             :         /* compare */
    5029                 :             :         nCurSymm = nCurRank = 0;
    5030                 :             :         for (i = 0; i < num_atoms; i++)
    5031                 :             :         {
    5032                 :             :             j = (int) nAtomNumber[i];
    5033                 :             :             if (nCurSymm != nSymmRank[j])
    5034                 :             :             {
    5035                 :             :                 nCurSymm = nSymmRank[j];
    5036                 :             :                 is = i;
    5037                 :             :             }
    5038                 :             :             if (nCurRank != nRank[j])
    5039                 :             :             {
    5040                 :             :                 nCurRank = nRank[j];
    5041                 :             :                 ir = i;
    5042                 :             :             }
    5043                 :             :             if (is != ir)
    5044                 :             :             {
    5045                 :             :                 bIsNotSame = 1;
    5046                 :             :                 break;
    5047                 :             :             }
    5048                 :             :         }
    5049                 :             :     }
    5050                 :             : 
    5051                 :             : exit_err:
    5052                 :             :     if (nRank)
    5053                 :             :         inchi_free( nRank );
    5054                 :             :     if (nAtomNumber)
    5055                 :             :         inchi_free( nAtomNumber );
    5056                 :             :     if (nTempRank)
    5057                 :             :         inchi_free( nTempRank );
    5058                 :             :     if (pAtomInvariant)
    5059                 :             :         inchi_free( pAtomInvariant );
    5060                 :             :     if (NeighList)
    5061                 :             :         FreeNeighList( NeighList );
    5062                 :             : 
    5063                 :             :     return bIsNotSame;
    5064                 :             : }
    5065                 :             : 
    5066                 :             : #endif
    5067                 :             : 
    5068                 :             : 
    5069                 :             : /****************************************************************************/
    5070                 :         161 : int GetBaseCanonRanking( INCHI_CLOCK *ic,
    5071                 :             :                          int num_atoms,
    5072                 :             :                          int num_at_tg,
    5073                 :             :                          sp_ATOM* at[],
    5074                 :             :                          T_GROUP_INFO *t_group_info,
    5075                 :             :                          ATOM_SIZES s[],
    5076                 :             :                          BCN *pBCN,
    5077                 :             :                          struct tagInchiTime *ulTimeOutTime,
    5078                 :             :                          CANON_GLOBALS *pCG,
    5079                 :             :                          int bFixIsoFixedH,
    5080                 :             :                          int LargeMolecules )
    5081                 :             : {
    5082                 :         161 :     int ret = 0;
    5083                 :             :     int iBase;                   /* base structure index, always valid; = TAUT_YES except special fully non-taut mode */
    5084                 :             :     int iOther;                  /* other than basic structure index, usually non-taut; may be = iBase */
    5085                 :             :     int bReqNonTaut;             /* 1 => requested non-tautomeric results */
    5086                 :             :     int bReqTaut;                /* 1 => requested tautomeric results and the base structure is tautomeric */
    5087                 :             :     int bChanged;
    5088                 :             : 
    5089                 :         161 :     sp_ATOM *at_base = NULL;
    5090                 :         161 :     sp_ATOM *at_other = NULL;
    5091                 :             : 
    5092                 :         161 :     int bTautIgnoreIsotopic = 0;
    5093                 :             :     /*int bIgnoreIsotopic     = 0;*/
    5094                 :         161 :     int nNumCurrRanks = 0;
    5095                 :         161 :     int nMaxLenRankStack = 0;
    5096                 :         161 :     int num_max = num_at_tg;
    5097                 :             :     long lCount;
    5098                 :             : 
    5099                 :             :     /* local allocations */
    5100                 :         161 :     ATOM_INVARIANT2 *pAtomInvariant = NULL;
    5101                 :             :     NEIGH_LIST     *NeighList[TAUT_NUM];
    5102                 :         161 :     ConTable *Ct_Temp = NULL;
    5103                 :             : 
    5104                 :             :     /* initial partition for canonicalization */
    5105                 :         161 :     AT_RANK *nRank = NULL;
    5106                 :         161 :     AT_NUMB *nAtomNumber = NULL;
    5107                 :             : 
    5108                 :             :     /* canonicalization output */
    5109                 :             : 
    5110                 :         161 :     ConTable *Ct_NoH = NULL;
    5111                 :         161 :     AT_RANK *nCanonRankNoH = NULL;
    5112                 :         161 :     AT_NUMB *nAtomNumberCanonNoH = NULL;
    5113                 :         161 :     AT_RANK *nSymmRankNoH = NULL;
    5114                 :             : 
    5115                 :         161 :     ConTable *Ct_NoTautH = NULL;
    5116                 :         161 :     AT_RANK *nSymmRankNoTautH = NULL;
    5117                 :         161 :     AT_RANK *nCanonRankNoTautH = NULL;
    5118                 :         161 :     AT_NUMB *nAtomNumberCanonNoTautH = NULL;
    5119                 :         161 :     NUM_H   *numHNoTautH = NULL;
    5120                 :             :     int      lenNumHNoTautH;
    5121                 :             :     int      maxlenNumHNoTautH;
    5122                 :             : 
    5123                 :         161 :     ConTable *Ct_Base = NULL;
    5124                 :         161 :     AT_RANK *nSymmRankBase = NULL;
    5125                 :         161 :     AT_RANK *nCanonRankBase = NULL;
    5126                 :         161 :     AT_NUMB *nAtomNumberCanonBase = NULL;
    5127                 :         161 :     NUM_H   *numH = NULL;
    5128                 :         161 :     int      lenNumH = num_atoms;
    5129                 :         161 :     int      maxlenNumH = 0;
    5130                 :             : 
    5131                 :             : #if ( USE_AUX_RANKING == 1 )
    5132                 :         161 :     AT_RANK *nRankAux = NULL;
    5133                 :         161 :     AT_NUMB *nAtomNumberAux = NULL;
    5134                 :         161 :     ATOM_INVARIANT2 *pAtomInvariantAux = NULL;
    5135                 :             : #endif
    5136                 :             : 
    5137                 :         161 :     ConTable *Ct_FixH = NULL;
    5138                 :         161 :     AT_RANK *nSymmRankFixH = NULL;
    5139                 :         161 :     AT_RANK *nCanonRankFixH = NULL;
    5140                 :         161 :     AT_NUMB *nAtomNumberCanonFixH = NULL;
    5141                 :         161 :     NUM_H   *NumHfixed = NULL;
    5142                 :             :     int      maxlenNumHfixed;
    5143                 :             : 
    5144                 :             :     /* isotopic canonicalization */
    5145                 :             : 
    5146                 :         161 :     ConTable *Ct_NoTautHIso = NULL;
    5147                 :         161 :     AT_RANK *nSymmRankNoTautHIso = NULL;
    5148                 :         161 :     AT_RANK *nCanonRankNoTautHIso = NULL;
    5149                 :         161 :     AT_NUMB *nAtomNumberCanonNoTautHIso = NULL;
    5150                 :         161 :     AT_ISO_SORT_KEY *iso_sort_key_NoTautH = NULL;
    5151                 :         161 :     int              maxlen_iso_sort_key_NoTautH = 0;
    5152                 :         161 :     int              len_iso_sort_key_NoTautH = 0;
    5153                 :         161 :     int num_iso_NoTautH = 0, num_iso_NoAuxBase;
    5154                 :             : 
    5155                 :         161 :     ConTable *Ct_BaseIso = NULL;
    5156                 :         161 :     AT_RANK *nSymmRankBaseIso = NULL;
    5157                 :         161 :     AT_RANK *nCanonRankBaseIso = NULL;
    5158                 :         161 :     AT_NUMB *nAtomNumberCanonBaseIso = NULL;
    5159                 :             : 
    5160                 :         161 :     AT_ISO_SORT_KEY *iso_sort_keyBase = NULL;
    5161                 :         161 :     int              maxlen_iso_sort_keyBase = 0;
    5162                 :         161 :     int              len_iso_sort_keyBase = 0;
    5163                 :             : 
    5164                 :             :     int              bUseIsoAuxBase[TAUT_NUM];
    5165                 :         161 :     S_CHAR          *iso_exchg_atnos = NULL;
    5166                 :         161 :     int              len_iso_exchg_atnos = 0;
    5167                 :         161 :     int              maxlen_iso_exchg_atnos = 0;
    5168                 :         161 :     int num_iso_Base = 0;
    5169                 :             : 
    5170                 :             :     AT_ISO_SORT_KEY  iso_sort_key;
    5171                 :             : 
    5172                 :         161 :     ConTable *Ct_FixHIso = NULL;
    5173                 :         161 :     AT_RANK *nSymmRankFixHIso = NULL;
    5174                 :         161 :     AT_RANK *nCanonRankFixHIso = NULL;
    5175                 :         161 :     AT_NUMB *nAtomNumberCanonFixHIso = NULL;
    5176                 :             : 
    5177                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    5178                 :             :     AT_ISO_SORT_KEY  iso_sort_key2;
    5179                 :             :     AT_ISO_SORT_KEY *iso_sort_key_Hfixed = NULL;
    5180                 :             :     int              maxlen_iso_sort_key_Hfixed;
    5181                 :             :     int              len_iso_sort_key_Hfixed;
    5182                 :             :     int num_iso_Hfixed;
    5183                 :             : #endif
    5184                 :             : 
    5185                 :         161 :     AT_RANK *nTempRank = NULL;
    5186                 :             : 
    5187                 :             :     CANON_DATA    pCD[3]; /* = &CanonData; */
    5188                 :             :     CANON_COUNTS  CanonCounts;
    5189                 :         161 :     CANON_COUNTS *pCC = &CanonCounts;
    5190                 :             : 
    5191                 :             :     int i, j, k, m;
    5192                 :             :     int nCanonFlags[2];
    5193                 :             : 
    5194                 :             :     /* */
    5195                 :             :     int iflag;
    5196                 :             : 
    5197                 :         161 :     memset( pCD, 0, sizeof( pCD ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5198                 :         161 :     memset( pCC, 0, sizeof( pCC[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5199                 :         161 :     memset( bUseIsoAuxBase, 0, sizeof( bUseIsoAuxBase ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5200                 :         161 :     memset( nCanonFlags, 0, sizeof( nCanonFlags ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5201                 :         161 :     NeighList[TAUT_NON] = NULL;
    5202                 :         161 :     NeighList[TAUT_YES] = NULL;
    5203                 :             : 
    5204                 :             :     /* select base structure, find whether it is tautomeric or not */
    5205                 :             :     /* djb-rwth: addressing LLVM warning */
    5206   [ +  -  +  -  :         161 :     if (at[TAUT_YES] && s[TAUT_YES].nLenCT &&
                   +  - ]
    5207         [ +  + ]:         161 :          t_group_info && ( s[TAUT_YES].nLenLinearCTTautomer > 0 && /* ordinary tautomerism */
    5208   [ +  -  +  + ]:          14 :              ((t_group_info->t_group && t_group_info->num_t_groups > 0) ||
    5209                 :             :              /* protons have been moved */
    5210         [ -  + ]:           7 :              ( t_group_info->tni.bNormalizationFlags & FLAG_NORM_CONSIDER_TAUT ) ||
    5211                 :             :              /* tautomerism due to possible isotopic proton exchange */
    5212         [ #  # ]:           0 :              (t_group_info->nNumIsotopicEndpoints > 1 &&
    5213         [ #  # ]:           0 :              ( t_group_info->bTautFlagsDone & ( TG_FLAG_FOUND_ISOTOPIC_H_DONE | TG_FLAG_FOUND_ISOTOPIC_ATOM_DONE ) ))) ))
    5214                 :             :     {
    5215                 :             :         /* tautomeric: (1) has tautomeric atoms OR
    5216                 :             :                        (2) H-atoms have been rearranged due to proton addition/removal OR
    5217                 :             :                        (3) Found isotopic H-atoms on tautomeric or hetero atoms
    5218                 :             :          */
    5219                 :          14 :         iBase = TAUT_YES;
    5220                 :          14 :         bReqTaut = 1;
    5221         [ -  + ]:          14 :         bUseIsoAuxBase[iBase] = ( s[iBase].nLenIsotopicEndpoints > 1 ) &&
    5222         [ #  # ]:           0 :             ( t_group_info->bTautFlagsDone & ( TG_FLAG_FOUND_ISOTOPIC_H_DONE | TG_FLAG_FOUND_ISOTOPIC_ATOM_DONE ) );
    5223   [ -  +  -  - ]:          14 :         if (at[TAUT_NON] && s[TAUT_NON].nLenCT)
    5224                 :             :         {
    5225                 :           0 :             iOther = TAUT_NON; /* tautomeric and non-tautomeric */
    5226                 :           0 :             bReqNonTaut = 1;
    5227                 :             :         }
    5228                 :             :         else
    5229                 :             :         {
    5230                 :          14 :             iOther = iBase; /* tautomeric only */
    5231                 :          14 :             bReqNonTaut = 0;
    5232                 :             :         }
    5233                 :             :     }
    5234                 :             : 
    5235   [ -  +  -  - ]:         147 :     else if (at[TAUT_NON] && s[TAUT_NON].nLenCT)
    5236                 :             :     {
    5237                 :             :         /* force pure non-tautomeric processing; happens for testing only */
    5238                 :           0 :         iBase = TAUT_NON;
    5239                 :           0 :         bReqTaut = 0;
    5240                 :           0 :         iOther = iBase;
    5241                 :           0 :         bReqNonTaut = 1;
    5242                 :           0 :         num_at_tg = num_atoms;
    5243                 :             :     }
    5244                 :             : 
    5245   [ +  -  +  - ]:         147 :     else if (at[TAUT_YES] && s[TAUT_YES].nLenCT)
    5246                 :             :     {
    5247                 :             :         /* although the user requested tautomeric processing, tautomerism has not been found */
    5248                 :             :         /* however, the results should be saved in the TAUT_YES elements of the arrays */
    5249                 :         147 :         iBase = TAUT_YES;
    5250                 :         147 :         bReqTaut = 0;
    5251                 :         147 :         bUseIsoAuxBase[iBase] = ( s[iBase].nLenIsotopicEndpoints > 1 );
    5252                 :         147 :         iOther = iBase;
    5253                 :         147 :         bReqNonTaut = 1;
    5254                 :         147 :         num_at_tg = num_atoms;
    5255                 :             :     }
    5256                 :             :     else
    5257                 :             :     {
    5258                 :           0 :         ret = CT_UNKNOWN_ERR;
    5259                 :           0 :         goto exit_error;
    5260                 :             :     }
    5261                 :             : 
    5262                 :             : 
    5263         [ +  + ]:         161 :     if (bReqTaut)
    5264                 :             :     {
    5265                 :             :         /* save "process isotopic" mark; temporarily set it to NO */
    5266                 :          14 :         bTautIgnoreIsotopic = t_group_info->bIgnoreIsotopic;
    5267                 :          14 :         t_group_info->bIgnoreIsotopic = 1;
    5268                 :             :     }
    5269                 :             : 
    5270                 :             :     /* djb-rwth: removing redundant code */
    5271                 :             : 
    5272                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    5273                 :             :     num_iso_Hfixed =
    5274                 :             :         len_iso_sort_key_Hfixed =
    5275                 :             :         maxlen_iso_sort_key_Hfixed = 0;
    5276                 :             : #endif
    5277                 :             : 
    5278                 :             :     /* prepare initial data */
    5279                 :         161 :     at_base = at[iBase];
    5280                 :         161 :     at_other = at[iOther];
    5281                 :         161 :     pAtomInvariant = (ATOM_INVARIANT2 *) inchi_calloc( num_max, sizeof( pAtomInvariant[0] ) );
    5282                 :         161 :     nSymmRankNoH = (AT_RANK *) inchi_calloc( num_max, sizeof( nSymmRankNoH[0] ) );
    5283                 :         161 :     nCanonRankNoH = (AT_RANK *) inchi_calloc( num_max, sizeof( nCanonRankNoH[0] ) );
    5284                 :         161 :     nAtomNumberCanonNoH = (AT_NUMB *) inchi_calloc( num_max, sizeof( nAtomNumberCanonNoH[0] ) );
    5285                 :         161 :     nRank = (AT_RANK *) inchi_calloc( num_max, sizeof( nRank[0] ) );
    5286                 :         161 :     nAtomNumber = (AT_NUMB *) inchi_calloc( num_max, sizeof( nAtomNumber[0] ) );
    5287                 :         161 :     nTempRank = (AT_RANK *) inchi_calloc( num_max, sizeof( nTempRank[0] ) );
    5288                 :             : 
    5289   [ +  -  +  - ]:         161 :     if (!pAtomInvariant ||
    5290   [ +  -  +  -  :         161 :          !nSymmRankNoH || !nCanonRankNoH || !nAtomNumberCanonNoH ||
                   +  - ]
    5291   [ +  -  -  + ]:         161 :          !nRank || !nAtomNumber || !nTempRank)
    5292                 :             :     {
    5293                 :           0 :         goto exit_error_alloc;
    5294                 :             :     }
    5295                 :             : 
    5296                 :             : #if ( USE_AUX_RANKING == 1 )
    5297                 :         161 :     nRankAux = (AT_RANK *) inchi_calloc( num_max, sizeof( nRankAux[0] ) );
    5298                 :         161 :     nAtomNumberAux = (AT_NUMB *) inchi_calloc( num_max, sizeof( nAtomNumberAux[0] ) );
    5299                 :         161 :     pAtomInvariantAux = (ATOM_INVARIANT2 *) inchi_malloc( num_max * sizeof( pAtomInvariantAux[0] ) );
    5300   [ +  -  +  -  :         161 :     if (!nRankAux || !nAtomNumberAux || !pAtomInvariantAux)
                   -  + ]
    5301                 :             :     {
    5302                 :           0 :         goto exit_error_alloc;
    5303                 :             :     }
    5304                 :             : #endif
    5305                 :             : 
    5306         [ +  + ]:         161 :     if (bReqTaut)
    5307                 :             :     {
    5308         [ -  + ]:          14 :         if (!( NeighList[TAUT_YES] =
    5309                 :          14 :                CreateNeighList( num_atoms, num_at_tg, at_base, 0, t_group_info ) ))
    5310                 :             :         {
    5311                 :           0 :             goto exit_error_alloc;
    5312                 :             :         }
    5313                 :             :         /* needed for the hydrogenless structure */
    5314         [ -  + ]:          14 :         if (!( NeighList[TAUT_NON] =
    5315                 :          14 :                CreateNeighList( num_atoms, num_atoms, at_base, 0, NULL ) ))
    5316                 :             :         {
    5317                 :           0 :             goto exit_error_alloc;
    5318                 :             :         }
    5319                 :             :     }
    5320                 :             :     else
    5321                 :             :     {
    5322         [ -  + ]:         147 :         if (!( NeighList[TAUT_NON] =
    5323                 :         147 :                CreateNeighList( num_atoms, num_atoms, at_base, 0, NULL ) ))
    5324                 :             :         {
    5325                 :           0 :             goto exit_error_alloc;
    5326                 :             :         }
    5327                 :         147 :         NeighList[TAUT_YES] = NULL;
    5328                 :             : 
    5329                 :             :         INCHI_HEAPCHK
    5330                 :             :     }
    5331                 :             : 
    5332                 :             : 
    5333                 :             :     /* avoid memory leaks in case of error */
    5334                 :             :     /*
    5335                 :             :     pBCN->ftcn[TAUT_NON].NeighList          = NeighList[TAUT_NON];
    5336                 :             :     pBCN->ftcn[TAUT_YES].NeighList          = NeighList[TAUT_YES];
    5337                 :             :     */
    5338                 :         161 :     pBCN->nMaxLenRankStack = 0;
    5339                 :         161 :     pBCN->num_max = num_max;        /* allocated nRank[] arrays lengths in pRankStack */
    5340                 :         161 :     pBCN->num_at_tg = num_at_tg;  /* all of the following arrays have this length */
    5341                 :         161 :     pBCN->num_atoms = num_atoms;
    5342                 :         161 :     pBCN->ulTimeOutTime = ulTimeOutTime;
    5343                 :             : 
    5344                 :             :     /* initial partitioning of a hydrogenless skeleton: fill out the inveriant */
    5345                 :         161 :     FillOutAtomInvariant2( at_base,
    5346                 :             :                            num_atoms,
    5347                 :             :                            num_atoms,
    5348                 :             :                            pAtomInvariant,
    5349                 :             :                            1 /*bIgnoreIsotopic*/,
    5350                 :             :                            0 /*bHydrogensInRanks*/,
    5351                 :             :                            0 /*bHydrogensFixedInRanks*/,
    5352                 :             :                            0 /*bTaut=bDigraph*/,
    5353                 :             :                            0 /* bTautGroupsOnly */,
    5354                 :             :                            NULL /*t_group_info*/ );
    5355                 :             : 
    5356                 :             :     /* initial partitioning of a hydrogenless skeleton: create equitable partition (assign initial ranks) */
    5357                 :         161 :     nNumCurrRanks = SetInitialRanks2( num_atoms, pAtomInvariant, nRank, nAtomNumber, pCG );
    5358                 :             : 
    5359                 :         161 :     lCount = 0;
    5360                 :             : 
    5361                 :             :     /* make equitable partition in pBCN->pRankStack[0,1] */
    5362                 :         161 :     nNumCurrRanks = DifferentiateRanks2( pCG,
    5363                 :             :                                          num_atoms,
    5364                 :             :                                          NeighList[TAUT_NON],
    5365                 :             :                                          nNumCurrRanks, nRank,
    5366                 :             :                                          nTempRank,
    5367                 :             :                                          nAtomNumber,
    5368                 :             :                                          &lCount,
    5369                 :             :                                          0 /* 0 means use qsort */ );
    5370                 :             : 
    5371                 :             :     /* allocate partition stack */
    5372                 :         161 :     nMaxLenRankStack = 2 * ( num_at_tg - nNumCurrRanks ) + 8;  /* was 2*(...) + 6 */
    5373                 :         161 :     pBCN->pRankStack = (AT_RANK **) inchi_calloc( nMaxLenRankStack, sizeof( pBCN->pRankStack[0] ) );
    5374         [ -  + ]:         161 :     if (!pBCN->pRankStack)
    5375                 :             :     {
    5376                 :           0 :         pBCN->nMaxLenRankStack = 0; /* avoid memory leaks in case of error */
    5377                 :           0 :         goto exit_error_alloc;
    5378                 :             :     }
    5379                 :         161 :     pBCN->nMaxLenRankStack = nMaxLenRankStack; /* avoid memory leaks in case of error */
    5380                 :             :     /* init partition stack */
    5381                 :         161 :     pBCN->pRankStack[0] = nRank;
    5382                 :         161 :     pBCN->pRankStack[1] = nAtomNumber;
    5383                 :             : 
    5384                 :             :     /********************************************************************************************/
    5385                 :             :     /* get NoH/no taut groups  canonical numbering, connection table, and equivalence partition */
    5386                 :             :     /********************************************************************************************/
    5387                 :             : 
    5388                 :             :     /* pointers */
    5389                 :         161 :     pCD[iOther].LinearCT = NULL;
    5390                 :         161 :     pCD[iOther].NumH = NULL;
    5391                 :         161 :     pCD[iOther].NumHfixed = NULL;
    5392                 :         161 :     pCD[iOther].iso_sort_key = NULL;
    5393                 :         161 :     pCD[iOther].iso_exchg_atnos = NULL;
    5394                 :             : 
    5395                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    5396                 :             :     pCD[iOther].iso_sort_key_Hfixed = NULL;
    5397                 :             : #endif
    5398                 :             : 
    5399                 :             :     /* variables - unchanged */
    5400                 :         161 :     pCD[iOther].ulTimeOutTime = pBCN->ulTimeOutTime;
    5401                 :         161 :     pCD[iOther].nMaxLenLinearCT = s[iOther].nLenCTAtOnly + 1;
    5402                 :             :     /* return values & input/output */
    5403                 :         161 :     pCD[iOther].nLenLinearCT = s[iOther].nLenCTAtOnly;
    5404                 :         161 :     pCD[iOther].nLenCTAtOnly = s[iOther].nLenCTAtOnly;
    5405                 :         161 :     pCD[iOther].lenNumH = 0;
    5406                 :         161 :     pCD[iOther].lenNumHfixed = 0;
    5407                 :         161 :     pCD[iOther].len_iso_sort_key = 0;
    5408                 :         161 :     pCD[iOther].maxlen_iso_sort_key = 0;
    5409                 :         161 :     pCD[iOther].len_iso_exchg_atnos = 0;
    5410                 :         161 :     pCD[iOther].maxlen_iso_exchg_atnos = 0;
    5411                 :             : 
    5412                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    5413                 :             :     pCD[iOther].len_iso_sort_key_Hfixed = 0;
    5414                 :             :     pCD[iOther].maxlen_iso_sort_key_Hfixed = 0;
    5415                 :             : #endif
    5416                 :             : 
    5417                 :         161 :     ret = CanonGraph01( ic, pCG, num_atoms, num_atoms, num_max, 0,
    5418                 :         161 :                         NeighList[TAUT_NON], (Partition *) pBCN->pRankStack,
    5419                 :             :                         nSymmRankNoH, nCanonRankNoH, nAtomNumberCanonNoH,
    5420                 :         161 :                         pCD + iOther, pCC, NULL, &Ct_NoH, LargeMolecules );
    5421                 :             : 
    5422         [ -  + ]:         161 :     if (ret < 0)
    5423                 :             :     {
    5424                 :           0 :         goto exit_error;
    5425                 :             :     }
    5426                 :             : 
    5427                 :             :     /* update initial partitioning */
    5428                 :         161 :     nNumCurrRanks = FixCanonEquivalenceInfo( pCG, num_atoms, nSymmRankNoH, nRank, nTempRank, nAtomNumber, &bChanged ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    5429                 :             : 
    5430                 :             :     /* repartition if necessary */
    5431         [ -  + ]:         161 :     if (bChanged & 3)
    5432                 :             :     {
    5433         [ #  # ]:           0 :         if (Ct_NoH)
    5434                 :             :         {
    5435                 :           0 :             CTableFree( Ct_NoH );
    5436         [ #  # ]:           0 :             inchi_free( Ct_NoH );
    5437                 :           0 :             Ct_NoH = NULL;
    5438                 :             :         }
    5439                 :           0 :         pCD[iOther].nCanonFlags |= CANON_FLAG_NO_H_RECANON;
    5440                 :             : 
    5441                 :           0 :         ret = CanonGraph02( ic, pCG, num_atoms, num_atoms, num_max, 0,
    5442                 :           0 :                             NeighList[TAUT_NON], (Partition *) pBCN->pRankStack,
    5443                 :             :                             nSymmRankNoH, nCanonRankNoH, nAtomNumberCanonNoH,
    5444                 :           0 :                             pCD + iOther, pCC, NULL, &Ct_NoH, LargeMolecules );
    5445                 :             : 
    5446         [ #  # ]:           0 :         if (ret < 0)
    5447                 :             :         {
    5448                 :           0 :             goto exit_error;
    5449                 :             :         }
    5450                 :             :     }
    5451                 :             : 
    5452                 :             : 
    5453                 :             :     /********************************************************************************/
    5454                 :             :     /* get NoTautH canonical numbering, connection table, and equivalence partition */
    5455                 :             :     /********************************************************************************/
    5456                 :         161 :     maxlenNumHNoTautH = num_atoms + 1;
    5457                 :         161 :     nSymmRankNoTautH = (AT_RANK *) inchi_calloc( num_max, sizeof( nSymmRankNoTautH[0] ) );
    5458                 :         161 :     nCanonRankNoTautH = (AT_RANK *) inchi_calloc( num_max, sizeof( nCanonRankNoTautH[0] ) );
    5459                 :         161 :     nAtomNumberCanonNoTautH = (AT_NUMB *) inchi_calloc( num_max, sizeof( nAtomNumberCanonNoTautH[0] ) );
    5460                 :         161 :     numHNoTautH = (NUM_H *) inchi_calloc( maxlenNumHNoTautH, sizeof( numHNoTautH[0] ) );
    5461   [ +  -  +  -  :         161 :     if (!numHNoTautH || !nSymmRankNoTautH || !nCanonRankNoTautH || !nAtomNumberCanonNoTautH)
             +  -  -  + ]
    5462                 :             :     {
    5463                 :           0 :         goto exit_error_alloc;
    5464                 :             :     }
    5465                 :             : 
    5466                 :             :     /* find number of H atoms attached to not-a-tautomeric-endpoint atoms */
    5467         [ +  + ]:         971 :     for (i = 0; i < num_atoms; i++)
    5468                 :             :     {
    5469   [ +  +  +  + ]:         810 :         numHNoTautH[i] = ( !at_base[i].endpoint && at_base[i].num_H ) ? at_base[i].num_H + BASE_H_NUMBER : EMPTY_H_NUMBER;
    5470                 :             :     }
    5471                 :             : 
    5472                 :             :     /* pointers */
    5473                 :         161 :     pCD[iOther].LinearCT = NULL;
    5474                 :         161 :     pCD[iOther].NumH = numHNoTautH;
    5475                 :         161 :     pCD[iOther].NumHfixed = NULL;
    5476                 :         161 :     pCD[iOther].iso_sort_key = NULL;
    5477                 :         161 :     pCD[iOther].iso_exchg_atnos = NULL;
    5478                 :             : 
    5479                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    5480                 :             :     pCD[iOther].iso_sort_key_Hfixed = NULL;
    5481                 :             : #endif
    5482                 :             : 
    5483                 :             :     /* variables - unchanged */
    5484                 :         161 :     pCD[iOther].ulTimeOutTime = pBCN->ulTimeOutTime;
    5485                 :         161 :     pCD[iOther].nMaxLenLinearCT = s[iOther].nLenCTAtOnly + 1;
    5486                 :         161 :     pCD[iOther].maxlenNumH = maxlenNumHNoTautH;
    5487                 :             :     /* return values & input/output */
    5488                 :         161 :     pCD[iOther].nLenLinearCT = s[iOther].nLenCTAtOnly;
    5489                 :         161 :     pCD[iOther].nLenCTAtOnly = s[iOther].nLenCTAtOnly;
    5490                 :         161 :     pCD[iOther].lenNumH = lenNumHNoTautH = num_atoms;
    5491                 :         161 :     pCD[iOther].lenNumHfixed = 0;
    5492                 :         161 :     pCD[iOther].len_iso_sort_key = 0;
    5493                 :         161 :     pCD[iOther].maxlen_iso_sort_key = 0;
    5494                 :         161 :     pCD[iOther].len_iso_exchg_atnos = 0;
    5495                 :         161 :     pCD[iOther].maxlen_iso_exchg_atnos = 0;
    5496                 :             : 
    5497                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    5498                 :             :     pCD[iOther].len_iso_sort_key_Hfixed = 0;
    5499                 :             :     pCD[iOther].maxlen_iso_sort_key_Hfixed = 0;
    5500                 :             : #endif
    5501                 :             : 
    5502                 :         161 :     pCD[iOther].nAuxRank = NULL;
    5503                 :             : 
    5504                 :             :     /* check whether we need NoTautH cononicalization */
    5505                 :         161 :     memset( nTempRank, 0, num_max * sizeof( nTempRank[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5506         [ +  + ]:         971 :     for (i = 0; i < num_atoms; i++)
    5507                 :             :     {
    5508         [ +  + ]:         810 :         if (nTempRank[nSymmRankNoH[i] - 1] < i)
    5509                 :             :         {
    5510                 :         649 :             nTempRank[nSymmRankNoH[i] - 1] = i; /* greatest class representative */
    5511                 :             :         }
    5512                 :             :     }
    5513         [ +  + ]:         971 :     for (i = 0; i < num_atoms; i++)
    5514                 :             :     {
    5515         [ -  + ]:         810 :         if (numHNoTautH[i] != numHNoTautH[nTempRank[nSymmRankNoH[i] - 1]])
    5516                 :             :         {
    5517                 :           0 :             pCD[iOther].nCanonFlags |= CANON_FLAG_NO_TAUT_H_DIFF;
    5518                 :           0 :             break; /* atoms so far found to be equivalent have different number of H; the canonicalization is needed */
    5519                 :             :         }
    5520                 :             :     }
    5521                 :             : 
    5522                 :             :     /* i = 0; *//* debug: force to call the canonicalization */
    5523         [ -  + ]:         161 :     if (i < num_atoms)
    5524                 :             :     {
    5525                 :             :         /* needs canonicalization */
    5526                 :             :         /* get aux canonical ranking of the structure with attached H */
    5527                 :             : 
    5528                 :             : #if ( USE_AUX_RANKING == 1 )
    5529                 :             :         /* refine no-H partition according to not-a-taut-H distribution */
    5530                 :           0 :         memset( pAtomInvariantAux, 0, num_max * sizeof( pAtomInvariantAux[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5531         [ #  # ]:           0 :         for (i = 0; i < num_atoms; i++)
    5532                 :             :         {
    5533                 :           0 :             pAtomInvariantAux[i].val[0] = nSymmRankNoH[i];
    5534                 :           0 :             pAtomInvariantAux[i].val[1] = numHNoTautH[i]; /* additional differentiation: not-a-taut-H distribution */
    5535                 :             :         }
    5536                 :             : 
    5537                 :             :         /* initial partitioning */
    5538                 :           0 :         nNumCurrRanks = SetInitialRanks2( num_atoms, pAtomInvariantAux, nRankAux, nAtomNumberAux, pCG );
    5539                 :             : 
    5540                 :             :         /* make equitable partition */
    5541                 :           0 :         nNumCurrRanks = DifferentiateRanks2( pCG, num_atoms, NeighList[TAUT_NON],
    5542                 :             :                                             nNumCurrRanks, nRankAux,
    5543                 :             :                                             nTempRank, nAtomNumberAux, &lCount, 0 /* 0 means use qsort */ ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    5544                 :             : 
    5545                 :             :         /* to accelerate do not call CanonGraph() to find really equivalent atoms */
    5546                 :           0 :         pCD[iOther].nAuxRank = nRankAux;
    5547                 :             : #endif
    5548                 :             : 
    5549                 :           0 :         ret = CanonGraph03( ic, pCG, num_atoms, num_atoms, num_max, 1 /* digraph?? was 0 */,
    5550                 :           0 :                             NeighList[TAUT_NON], (Partition *) pBCN->pRankStack,
    5551                 :             :                             nSymmRankNoTautH, nCanonRankNoTautH, nAtomNumberCanonNoTautH,
    5552                 :           0 :                             pCD + iOther, pCC, &Ct_NoH, &Ct_NoTautH, LargeMolecules );
    5553                 :             : 
    5554         [ #  # ]:           0 :         if (ret < 0)
    5555                 :             :         {
    5556                 :           0 :             goto exit_error;
    5557                 :             :         }
    5558                 :             : 
    5559                 :             :         /* in case of non-tautomeric structure the final results are in:
    5560                 :             : 
    5561                 :             :                    nSymmRankNoTautH
    5562                 :             :                    nCanonRankNoTautH
    5563                 :             :                    nAtomNumberCanonNoTautH
    5564                 :             :                    Ct_NoTautH
    5565                 :             :                    numHNoTautH (original H positions)
    5566                 :             :         */
    5567                 :             :     } /* if ( i < num_atoms )  */
    5568                 :             : 
    5569                 :             :     else
    5570                 :             : 
    5571                 :             :     {
    5572                 :             : 
    5573                 :             :         /* copy the results of the previous (no H) canonicalization */
    5574                 :             :         /* in this case numHNoTautH[] is not needed for the next canonicalization(s) */
    5575   [ +  -  +  - ]:         322 :         if (( Ct_Temp = (ConTable *) inchi_calloc( 1, sizeof( *Ct_Temp ) ) ) &&
    5576                 :         161 :              CTableCreate( Ct_Temp, num_atoms, pCD + iOther ))
    5577                 :             :         {
    5578                 :         161 :             CtFullCopy( Ct_Temp, Ct_NoH );
    5579                 :             :             /* since Ct_NoH does not have Ct_NoH->NumH we have to fill out Ct_Temp->NumH separately */
    5580         [ +  + ]:         971 :             for (i = 0; i < num_atoms; i++)
    5581                 :             :             {
    5582                 :         810 :                 Ct_Temp->NumH[nCanonRankNoH[i] - 1] = numHNoTautH[i];
    5583                 :             :                 /*Ct_Temp->NumH[i] = numHNoTautH[nAtomNumberCanonNoH[i]]; -- alternative */
    5584                 :             :             }
    5585                 :         161 :             Ct_Temp->lenNumH = num_atoms;
    5586                 :             :         }
    5587                 :             :         else
    5588                 :             :         {
    5589                 :           0 :             goto exit_error_alloc;
    5590                 :             :         }
    5591                 :             : 
    5592                 :         161 :         Ct_NoTautH = Ct_Temp;
    5593                 :         161 :         Ct_Temp = NULL;
    5594                 :             :         /* djb-rwth: functions replaced with their safe C11 variants */
    5595                 :         161 :         memcpy(nSymmRankNoTautH, nSymmRankNoH, num_atoms * sizeof(nSymmRankNoTautH[0]));
    5596                 :         161 :         memcpy(nCanonRankNoTautH, nCanonRankNoH, num_atoms * sizeof(nCanonRankNoTautH[0]));
    5597                 :         161 :         memcpy(nAtomNumberCanonNoTautH, nAtomNumberCanonNoH, num_atoms * sizeof(nAtomNumberCanonNoTautH[0]));
    5598                 :             :     }
    5599                 :             : 
    5600                 :             :     /* in case of non-tautomeric component this is the final result */
    5601                 :             :     /* i = CtFullCompare( Ct_NoTautH, Ct_Temp, num_atoms, 0, 0 );*/
    5602                 :             : 
    5603                 :             :     /*******************************************************************************************/
    5604                 :             :     /* If only Isotopic atoms and isotopic H, tautomerism has not been found:                  */
    5605                 :             :     /* get isotopic canonical numbering, connection table, and equivalence partition           */
    5606                 :             :     /*******************************************************************************************/
    5607                 :             : 
    5608   [ -  +  -  -  :         161 :     if (s[iOther].num_isotopic_atoms && !s[iOther].bIgnoreIsotopic && !bReqTaut && bReqNonTaut)
             -  -  -  - ]
    5609                 :             :     {
    5610                 :             : 
    5611                 :           0 :         maxlen_iso_sort_key_NoTautH = num_atoms + 1;
    5612                 :           0 :         nSymmRankNoTautHIso = (AT_RANK *) inchi_calloc( num_max, sizeof( nSymmRankNoTautHIso[0] ) );
    5613                 :           0 :         nCanonRankNoTautHIso = (AT_RANK *) inchi_calloc( num_max, sizeof( nCanonRankNoTautHIso[0] ) );
    5614                 :           0 :         nAtomNumberCanonNoTautHIso = (AT_NUMB *) inchi_calloc( num_max, sizeof( nAtomNumberCanonNoTautHIso[0] ) );
    5615                 :           0 :         iso_sort_key_NoTautH = (AT_ISO_SORT_KEY *) inchi_calloc( maxlen_iso_sort_key_NoTautH, sizeof( iso_sort_key_NoTautH[0] ) );
    5616                 :             : 
    5617   [ #  #  #  #  :           0 :         if (!nSymmRankNoTautHIso || !nCanonRankNoTautHIso || !nAtomNumberCanonNoTautHIso || !iso_sort_key_NoTautH)
             #  #  #  # ]
    5618                 :             :         {
    5619                 :           0 :             goto exit_error_alloc;
    5620                 :             :         }
    5621                 :             : 
    5622                 :             :         /* fill out isotopic non-tautomeric keys */
    5623                 :           0 :         num_iso_NoTautH = 0;
    5624         [ #  # ]:           0 :         for (i = 0; i < num_atoms; i++)
    5625                 :             :         {
    5626         [ #  # ]:           0 :             if (at_base[i].endpoint)
    5627                 :             :             {
    5628                 :             :                 /* should not happen */
    5629                 :           0 :                 iso_sort_key = make_iso_sort_key( at_base[i].iso_atw_diff, 0, 0, 0 );
    5630                 :             :             }
    5631                 :             :             else
    5632                 :             :             {
    5633                 :           0 :                 iso_sort_key = make_iso_sort_key( at_base[i].iso_atw_diff, at_base[i].num_iso_H[0], at_base[i].num_iso_H[1], at_base[i].num_iso_H[2] );
    5634                 :             :             }
    5635         [ #  # ]:           0 :             if (iso_sort_key)
    5636                 :             :             {
    5637                 :           0 :                 iso_sort_key_NoTautH[i] = iso_sort_key;
    5638                 :           0 :                 num_iso_NoTautH++;
    5639                 :             :             }
    5640                 :             :             else
    5641                 :             :             {
    5642                 :           0 :                 iso_sort_key_NoTautH[i] = EMPTY_ISO_SORT_KEY;
    5643                 :             :             }
    5644                 :             :         }
    5645                 :             : 
    5646                 :             :         /* pointers */
    5647                 :           0 :         pCD[iOther].LinearCT = NULL; /* LinearCT; */
    5648                 :           0 :         pCD[iOther].NumH = numHNoTautH;
    5649                 :           0 :         pCD[iOther].NumHfixed = NULL;
    5650                 :           0 :         pCD[iOther].iso_sort_key = iso_sort_key_NoTautH;
    5651                 :           0 :         pCD[iOther].iso_exchg_atnos = NULL;
    5652                 :             : 
    5653                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    5654                 :             :         pCD[iOther].iso_sort_key_Hfixed = NULL;
    5655                 :             : #endif
    5656                 :             : 
    5657                 :             :         /* variables - unchanged */
    5658                 :           0 :         pCD[iOther].ulTimeOutTime = pBCN->ulTimeOutTime;
    5659                 :           0 :         pCD[iOther].nMaxLenLinearCT = s[iOther].nLenCTAtOnly + 1;
    5660                 :           0 :         pCD[iOther].maxlenNumH = maxlenNumHNoTautH;
    5661                 :             :         /* return values & input/output */
    5662                 :           0 :         pCD[iOther].nLenLinearCT = s[iOther].nLenCTAtOnly;
    5663                 :           0 :         pCD[iOther].nLenCTAtOnly = s[iOther].nLenCTAtOnly;
    5664                 :           0 :         pCD[iOther].lenNumH = lenNumHNoTautH /*= num_atoms*/;
    5665                 :           0 :         pCD[iOther].lenNumHfixed = 0;
    5666                 :           0 :         pCD[iOther].len_iso_sort_key = len_iso_sort_key_NoTautH = num_atoms;
    5667                 :           0 :         pCD[iOther].maxlen_iso_sort_key = maxlen_iso_sort_key_NoTautH;
    5668                 :           0 :         pCD[iOther].len_iso_exchg_atnos = 0;
    5669                 :           0 :         pCD[iOther].maxlen_iso_exchg_atnos = 0;
    5670                 :             : 
    5671                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    5672                 :             :         pCD[iOther].len_iso_sort_key_Hfixed = 0;
    5673                 :             :         pCD[iOther].maxlen_iso_sort_key_Hfixed = 0;
    5674                 :             : #endif
    5675                 :             : 
    5676                 :           0 :         pCD[iOther].nAuxRank = NULL;
    5677                 :             : 
    5678         [ #  # ]:           0 :         if (num_iso_NoTautH)
    5679                 :             :         {
    5680                 :             :             /* check whether we need NoTautH cononicalization */
    5681                 :           0 :             memset( nTempRank, 0, num_max * sizeof( nTempRank[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5682         [ #  # ]:           0 :             for (i = 0; i < num_atoms; i++)
    5683                 :             :             {
    5684         [ #  # ]:           0 :                 if (nTempRank[nSymmRankNoTautH[i] - 1] < i)
    5685                 :             :                 {
    5686                 :           0 :                     nTempRank[nSymmRankNoTautH[i] - 1] = i; /* greatest class representative */
    5687                 :             :                 }
    5688                 :             :             }
    5689         [ #  # ]:           0 :             for (i = 0; i < num_atoms; i++)
    5690                 :             :             {
    5691         [ #  # ]:           0 :                 if (iso_sort_key_NoTautH[i] != iso_sort_key_NoTautH[nTempRank[nSymmRankNoTautH[i] - 1]])
    5692                 :             :                 {
    5693                 :           0 :                     pCD[iOther].nCanonFlags |= CANON_FLAG_ISO_ONLY_NON_TAUT_DIFF;
    5694                 :           0 :                     break; /* atoms so far found to be equivalent differ in isotopes; the canonicalization is needed */
    5695                 :             :                 }
    5696                 :             :             }
    5697                 :             :         }
    5698                 :             :         else
    5699                 :             :         {
    5700                 :           0 :             i = num_atoms;
    5701                 :             :         }
    5702                 :             :         /* i = 0; *//* debug: force to call the canonicalization */
    5703         [ #  # ]:           0 :         if (i < num_atoms)
    5704                 :             :         {
    5705                 :             :             /* we need canonicalization */
    5706                 :             :             /* get aux canonical ranking of the structure with isotopic non-tautomeric H */
    5707                 :             : 
    5708                 :             : #if ( USE_AUX_RANKING == 1 )
    5709                 :             :             /* refine no-taut-H partition according to non-taut H isotopic distribution */
    5710                 :           0 :             memset( pAtomInvariantAux, 0, num_max * sizeof( pAtomInvariantAux[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5711         [ #  # ]:           0 :             for (i = 0; i < num_atoms; i++)
    5712                 :             :             {
    5713                 :           0 :                 pAtomInvariantAux[i].val[0] = nSymmRankNoTautH[i];
    5714                 :           0 :                 pAtomInvariantAux[i].iso_sort_key = iso_sort_key_NoTautH[i]; /* additional differentiation */
    5715                 :             :             }
    5716                 :             :             /* initial ranks for non-taut H isotopic distribution */
    5717                 :           0 :             nNumCurrRanks = SetInitialRanks2( num_atoms, pAtomInvariantAux, nRankAux, nAtomNumberAux, pCG );
    5718                 :             :             /* make equitable */
    5719                 :           0 :             nNumCurrRanks = DifferentiateRanks2( pCG, num_atoms, NeighList[TAUT_NON],
    5720                 :             :                                                 nNumCurrRanks, nRankAux,
    5721                 :             :                                                 nTempRank, nAtomNumberAux, &lCount, 0 /* 0 means use qsort */ ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    5722                 :             :             /* to accelerate do not call CanonGraph() to find really equivalent atoms */
    5723                 :           0 :             pCD[iOther].nAuxRank = nRankAux;
    5724                 :             : #endif
    5725                 :             : 
    5726                 :           0 :             ret = CanonGraph04( ic, pCG,
    5727                 :             :                                 num_atoms, num_atoms, num_max, 1 /* digraph?? was 0 */,
    5728                 :           0 :                                 NeighList[TAUT_NON], (Partition *) pBCN->pRankStack,
    5729                 :             :                                 nSymmRankNoTautHIso, nCanonRankNoTautHIso, nAtomNumberCanonNoTautHIso,
    5730                 :           0 :                                 pCD + iOther, pCC, &Ct_NoTautH, &Ct_NoTautHIso, LargeMolecules );
    5731         [ #  # ]:           0 :             if (ret < 0)
    5732                 :             :             {
    5733                 :           0 :                 goto exit_error;
    5734                 :             :             }
    5735                 :             : 
    5736                 :             :             /* in case of non-tautomeric structure the final results are in:
    5737                 :             : 
    5738                 :             :                        nSymmRankNoTautHIso
    5739                 :             :                        nCanonRankNoTautHIso
    5740                 :             :                        nAtomNumberCanonNoTautHIso
    5741                 :             :                        Ct_NoTautHIso
    5742                 :             :                        iso_sort_key_NoTautH (original isotopic atom positions)
    5743                 :             :             */
    5744                 :             :         }
    5745                 :             :         else
    5746                 :             :         {
    5747                 :             :             /* copy the results of the previous (no taut H) canonicalization */
    5748                 :             :             /* in this case numHNoTautH[] is not needed for the next canonicalization(s) */
    5749   [ #  #  #  # ]:           0 :             if (( Ct_Temp = (ConTable *) inchi_calloc( 1, sizeof( *Ct_Temp ) ) ) &&
    5750                 :           0 :                  CTableCreate( Ct_Temp, num_atoms, pCD + iOther ))
    5751                 :             :             {
    5752                 :           0 :                 CtFullCopy( Ct_Temp, Ct_NoTautH );
    5753                 :             :                 /* since Ct_NoTautH does not have Ct_NoTautH->iso_sort_key we have to fill out Ct_Temp->iso_sort_key separately */
    5754         [ #  # ]:           0 :                 for (i = 0; i < num_atoms; i++)
    5755                 :             :                 {
    5756                 :           0 :                     Ct_Temp->iso_sort_key[nCanonRankNoTautH[i] - 1] = iso_sort_key_NoTautH[i];
    5757                 :             :                 }
    5758                 :           0 :                 Ct_Temp->len_iso_sort_key = num_atoms;
    5759                 :             :             }
    5760                 :             :             else
    5761                 :             :             {
    5762                 :           0 :                 goto exit_error_alloc;
    5763                 :             :             }
    5764                 :           0 :             Ct_NoTautHIso = Ct_Temp;
    5765                 :           0 :             Ct_Temp = NULL;
    5766                 :           0 :             memcpy(nSymmRankNoTautHIso, nSymmRankNoTautH, num_atoms * sizeof(nSymmRankNoTautHIso[0]));
    5767                 :           0 :             memcpy(nCanonRankNoTautHIso, nCanonRankNoTautH, num_atoms * sizeof(nCanonRankNoTautHIso[0]));
    5768                 :           0 :             memcpy(nAtomNumberCanonNoTautHIso, nAtomNumberCanonNoTautH, num_atoms * sizeof(nAtomNumberCanonNoTautHIso[0]));
    5769                 :             :         }
    5770                 :             :         /* in case of non-tautomeric component this is the final result */
    5771                 :             :         /* i = CtFullCompare( Ct_NoTautHIso, Ct_Temp, num_atoms, 0, 0 );*/
    5772                 :             :     }
    5773                 :             : 
    5774                 :             : 
    5775         [ +  + ]:         161 :     if (bReqTaut)
    5776                 :             :     {
    5777                 :             :         /*****************************************************************************/
    5778                 :             :         /* Tautomeric Structure Canonicalizaton:                                     */
    5779                 :             :         /* get base canonical numbering, connection table, and equivalence partition */
    5780                 :             :         /*****************************************************************************/
    5781                 :             :         /* find H atoms attached to non-tautomeric-endpoints and to tautomeric endpoints */
    5782                 :          14 :         maxlenNumH = num_atoms + T_NUM_NO_ISOTOPIC*( num_at_tg - num_atoms ) + 1; /* including negative charges */
    5783                 :          14 :         nSymmRankBase = (AT_RANK *) inchi_calloc( num_max, sizeof( nSymmRankBase[0] ) );
    5784                 :          14 :         nCanonRankBase = (AT_RANK *) inchi_calloc( num_max, sizeof( nCanonRankBase[0] ) );
    5785                 :          14 :         nAtomNumberCanonBase = (AT_NUMB *) inchi_calloc( num_max, sizeof( nAtomNumberCanonBase[0] ) );
    5786                 :          14 :         numH = (NUM_H *) inchi_calloc( maxlenNumH, sizeof( numH[0] ) );
    5787                 :             : 
    5788   [ +  -  +  -  :          14 :         if (!numH || !nSymmRankBase || !nCanonRankBase || !nAtomNumberCanonBase)
             +  -  -  + ]
    5789                 :             :         {
    5790                 :           0 :             goto exit_error_alloc;
    5791                 :             :         }
    5792                 :             : 
    5793                 :             :         /* non-tautomeric H counts */
    5794         [ +  + ]:          65 :         for (i = 0; i < num_atoms; i++)
    5795                 :             :         {
    5796   [ +  +  +  + ]:          51 :             numH[i] = ( !at_base[i].endpoint && at_base[i].num_H ) ? at_base[i].num_H + BASE_H_NUMBER : EMPTY_H_NUMBER;
    5797                 :             :         }
    5798                 :             : 
    5799                 :             :         /* tautomeric H and negative charge counts */
    5800         [ +  + ]:          26 :         for (i = k = num_atoms; i < num_at_tg; i++)
    5801                 :             :         {
    5802                 :          12 :             m = i - num_atoms;
    5803         [ +  + ]:          36 :             for (j = 0; j < T_NUM_NO_ISOTOPIC; j++)
    5804                 :             :             {
    5805                 :             :                 /* non-zeroes for j=1 are negative charge counts; T_NUM_NO_ISOTOPIC=2 entry per t-group */
    5806         [ +  + ]:          24 :                 numH[k++] = t_group_info->t_group[m].num[j] ? t_group_info->t_group[m].num[j] + BASE_H_NUMBER : EMPTY_H_NUMBER;
    5807                 :             :             }
    5808                 :             :         }
    5809                 :             : 
    5810                 :             :         /* pointers */
    5811                 :          14 :         pCD[iBase].LinearCT = NULL;
    5812                 :          14 :         pCD[iBase].NumH = numH; /* num_atoms non-tautomeric H; num_tg pairs of H and (-) in t-groups */
    5813                 :          14 :         pCD[iBase].NumHfixed = NULL;
    5814                 :          14 :         pCD[iBase].iso_sort_key = NULL;
    5815                 :          14 :         pCD[iBase].iso_exchg_atnos = NULL;
    5816                 :             : 
    5817                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    5818                 :             :         pCD[iBase].iso_sort_key_Hfixed = NULL;
    5819                 :             : #endif
    5820                 :             : 
    5821                 :             :         /* variables - unchanged */
    5822                 :          14 :         pCD[iBase].ulTimeOutTime = pBCN->ulTimeOutTime;
    5823                 :          14 :         pCD[iBase].nMaxLenLinearCT = s[iBase].nLenCT + 1;
    5824                 :          14 :         pCD[iBase].maxlenNumH = maxlenNumH;
    5825                 :             :         /* return values & input/output */
    5826                 :          14 :         pCD[iBase].nLenLinearCT = s[iBase].nLenCT;
    5827                 :          14 :         pCD[iBase].nLenCTAtOnly = s[iBase].nLenCTAtOnly;
    5828                 :          14 :         pCD[iBase].lenNumH = lenNumH = k;
    5829                 :          14 :         pCD[iBase].lenNumHfixed = 0;
    5830                 :          14 :         pCD[iBase].len_iso_sort_key = 0;
    5831                 :          14 :         pCD[iBase].maxlen_iso_sort_key = 0;
    5832                 :          14 :         pCD[iBase].len_iso_exchg_atnos = 0;
    5833                 :          14 :         pCD[iBase].maxlen_iso_exchg_atnos = 0;
    5834                 :             : 
    5835                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    5836                 :             :         pCD[iBase].len_iso_sort_key_Hfixed = 0;
    5837                 :             :         pCD[iBase].maxlen_iso_sort_key_Hfixed = 0;
    5838                 :             : #endif
    5839                 :             : 
    5840                 :          14 :         pCD[iBase].nAuxRank = NULL;
    5841                 :             : 
    5842                 :             :         /* make sure the initial partition is equitable (at this point t-groups do not have ranks yet) */
    5843                 :          14 :         FillOutAtomInvariant2( at_base,
    5844                 :             :                                num_atoms,
    5845                 :             :                                num_at_tg,
    5846                 :             :                                pAtomInvariant,
    5847                 :             :                                1 /*bIgnoreIsotopic*/,
    5848                 :             :                                0 /*bHydrogensInRanks*/,
    5849                 :             :                                0 /*bHydrogensFixedInRanks*/,
    5850                 :             :                                1 /*bTaut=bDigraph*/,
    5851                 :             :                                1 /* bTautGroupsOnly */,
    5852                 :             :                                t_group_info );
    5853                 :             : 
    5854         [ +  + ]:          65 :         for (i = 0; i < num_atoms; i++)
    5855                 :             :         {
    5856                 :          51 :             pAtomInvariant[i].val[0] = pBCN->pRankStack[0][i];
    5857                 :             :         }
    5858                 :             : 
    5859                 :             :         /* initial ranks for t-group(s) only */
    5860                 :          14 :         nNumCurrRanks = SetInitialRanks2( num_at_tg, pAtomInvariant, nRank, nAtomNumber, pCG );
    5861                 :             : 
    5862                 :             :         /* make equitable, call digraph procedure;
    5863                 :             :            pBCN->pRankStack[0] is nRank, pBCN->pRankStack[1] is nAtomNumber
    5864                 :             :            This should only split ranks of tautomeric groups */
    5865                 :          14 :         nNumCurrRanks = DifferentiateRanks4( pCG, num_at_tg, NeighList[TAUT_YES],
    5866                 :          14 :                                          nNumCurrRanks, pBCN->pRankStack[0], nTempRank /* temp array */,
    5867                 :          14 :                                          pBCN->pRankStack[1], (AT_RANK) num_atoms, &lCount ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    5868                 :             : 
    5869                 :             : #if ( USE_AUX_RANKING == 1 )
    5870                 :             :         /* refine no-H partition according to non-taut H distribution */
    5871                 :          14 :         memset( pAtomInvariantAux, 0, num_max * sizeof( pAtomInvariantAux[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5872         [ +  + ]:          65 :         for (i = 0; i < num_atoms; i++)
    5873                 :             :         {
    5874                 :          51 :             pAtomInvariantAux[i].val[0] = nSymmRankNoTautH[i];
    5875                 :          51 :             pAtomInvariantAux[i].val[1] = numH[i]; /* additional differentiation */
    5876                 :             :         }
    5877                 :             :         /*
    5878                 :             :         * djb-rwth: original badly written loop
    5879                 :             :         for (j = i; i < num_at_tg; i++)
    5880                 :             :         {
    5881                 :             :             pAtomInvariantAux[i].val[0] = nRank[i];
    5882                 :             :         }
    5883                 :             :         */
    5884         [ +  + ]:          26 :         for (j = i; j < num_at_tg; j++) /* djb-rwth: corrected loop */
    5885                 :             :         {
    5886                 :          12 :             pAtomInvariantAux[j].val[0] = nRank[j];
    5887                 :             :         }
    5888                 :             :         /* initial ranks for t-group(s) */
    5889                 :          14 :         nNumCurrRanks = SetInitialRanks2( num_at_tg, pAtomInvariantAux, nRankAux, nAtomNumberAux, pCG );
    5890                 :             :         /* make equitable, call digraph procedure */
    5891                 :          14 :         nNumCurrRanks = DifferentiateRanks4( pCG, num_at_tg, NeighList[TAUT_YES],
    5892                 :             :                                          nNumCurrRanks, nRankAux, nTempRank /* temp array */,
    5893                 :          14 :                                          nAtomNumberAux, (AT_RANK) num_atoms, &lCount ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    5894                 :             :         /* to accelerate do not call CanonGraph() to find really equivalent atoms */
    5895                 :          14 :         pCD[iBase].nAuxRank = nRankAux;
    5896                 :             : #endif
    5897                 :             : 
    5898                 :          14 :         ret = CanonGraph05( ic, pCG, num_atoms, num_at_tg, num_max, 1 /* digraph*/,
    5899                 :          14 :                             NeighList[TAUT_YES], (Partition *) pBCN->pRankStack,
    5900                 :             :                             nSymmRankBase, nCanonRankBase, nAtomNumberCanonBase,
    5901                 :          14 :                             pCD + iBase, pCC, &Ct_NoTautH, &Ct_Base, LargeMolecules );
    5902         [ -  + ]:          14 :         if (ret < 0)
    5903                 :             :         {
    5904                 :           0 :             goto exit_error;
    5905                 :             :         }
    5906                 :             : 
    5907                 :             :         /* tautomeric isotopic structure */
    5908                 :             :         /**************************************************************************************/
    5909                 :             :         /* Isotopic atoms and isotopic H atoms and isotopic tautomeric groups                 */
    5910                 :             :         /* get isotopic canonical numbering, connection table, and equivalence partition      */
    5911                 :             :         /**************************************************************************************/
    5912   [ -  +  -  - ]:          14 :         if ((s[iBase].num_isotopic_atoms && !s[iBase].bIgnoreIsotopic) ||
    5913   [ -  +  -  - ]:          14 :              (s[iBase].bHasIsotopicTautGroups && !bTautIgnoreIsotopic) ||
    5914   [ -  +  -  - ]:          14 :              (bUseIsoAuxBase[iBase] && !bTautIgnoreIsotopic)) /* djb-rwth: addressing LLVM warning */
    5915                 :             :         {
    5916                 :             : 
    5917                 :           0 :             t_group_info->bIgnoreIsotopic = bTautIgnoreIsotopic;
    5918                 :             : 
    5919                 :           0 :             nSymmRankBaseIso = (AT_RANK *) inchi_calloc( num_max, sizeof( nSymmRankBaseIso[0] ) );
    5920                 :           0 :             nCanonRankBaseIso = (AT_RANK *) inchi_calloc( num_max, sizeof( nCanonRankBaseIso[0] ) );
    5921                 :           0 :             nAtomNumberCanonBaseIso = (AT_NUMB *) inchi_calloc( num_max, sizeof( nAtomNumberCanonBaseIso[0] ) );
    5922         [ #  # ]:           0 :             if (bUseIsoAuxBase[iBase])
    5923                 :             :             {
    5924                 :           0 :                 maxlen_iso_exchg_atnos = num_max + 1;
    5925                 :           0 :                 iso_exchg_atnos = (S_CHAR  *) inchi_calloc( maxlen_iso_exchg_atnos, sizeof( iso_exchg_atnos[0] ) );
    5926                 :             :             }
    5927                 :           0 :             maxlen_iso_sort_keyBase = num_max + 1; /* num_at_tg+1;*/
    5928                 :           0 :             iso_sort_keyBase = (AT_ISO_SORT_KEY *) inchi_calloc( maxlen_iso_sort_keyBase, sizeof( iso_sort_keyBase[0] ) );
    5929   [ #  #  #  #  :           0 :             if (!nSymmRankBaseIso || !nCanonRankBaseIso || !nAtomNumberCanonBaseIso ||
             #  #  #  # ]
    5930         [ #  # ]:           0 :                  !iso_sort_keyBase ||
    5931         [ #  # ]:           0 :                  (maxlen_iso_exchg_atnos && !iso_exchg_atnos)) /* djb-rwth: addressing LLVM warning */
    5932                 :             :             {
    5933                 :           0 :                 goto exit_error_alloc;
    5934                 :             :             }
    5935                 :             :             /* atoms */
    5936                 :           0 :             num_iso_NoTautH = 0;
    5937                 :           0 :             num_iso_NoAuxBase = 0;
    5938         [ #  # ]:           0 :             if (iso_exchg_atnos)
    5939                 :             :             {
    5940                 :           0 :                 len_iso_exchg_atnos = num_at_tg;
    5941                 :             :             }
    5942         [ #  # ]:           0 :             for (i = 0; i < num_atoms; i++)
    5943                 :             :             {
    5944   [ #  #  #  #  :           0 :                 if (at_base[i].endpoint || (iso_exchg_atnos && ( at_base[i].cFlags & AT_FLAG_ISO_H_POINT ))) /* djb-rwth: addressing LLVM warning */
                   #  # ]
    5945                 :             :                 {
    5946                 :             :                     /* tautomeric or may have exchangeable isotopic H */
    5947                 :           0 :                     iso_sort_key = make_iso_sort_key( at_base[i].iso_atw_diff, 0, 0, 0 );
    5948         [ #  # ]:           0 :                     if (iso_exchg_atnos)
    5949                 :             :                     {
    5950                 :           0 :                         num_iso_NoAuxBase += !at_base[i].endpoint; /* these non-taut atom may exchange isotopic H as tautomeric atoms do */
    5951                 :             :                     }
    5952                 :             :                 }
    5953                 :             :                 else
    5954                 :             :                 {
    5955                 :             :                     /* non-mobile H */
    5956                 :           0 :                     iso_sort_key = make_iso_sort_key( at_base[i].iso_atw_diff, at_base[i].num_iso_H[0], at_base[i].num_iso_H[1], at_base[i].num_iso_H[2] );
    5957         [ #  # ]:           0 :                     if (iso_exchg_atnos)
    5958                 :             :                     {
    5959                 :           0 :                         iso_exchg_atnos[i] = 1; /* atom cannot have exchangable isotopic H atom(s) */
    5960                 :             :                     }
    5961                 :             :                 }
    5962         [ #  # ]:           0 :                 if (iso_sort_key)
    5963                 :             :                 {
    5964                 :           0 :                     num_iso_NoTautH++;
    5965                 :           0 :                     iso_sort_keyBase[i] = iso_sort_key;
    5966                 :             :                 }
    5967                 :             :                 else
    5968                 :             :                 {
    5969                 :           0 :                     iso_sort_keyBase[i] = EMPTY_ISO_SORT_KEY;
    5970                 :             :                 }
    5971                 :             :             }
    5972                 :             : 
    5973                 :             :             /* check marking and count of non-taut atoms that may exchange isotopic H -- debug only */
    5974         [ #  # ]:           0 :             if (iso_exchg_atnos)
    5975                 :             :             {
    5976         [ #  # ]:           0 :                 if (num_iso_NoAuxBase != t_group_info->nIsotopicEndpointAtomNumber[0])
    5977                 :             :                 {
    5978                 :           0 :                     ret = CT_ISOCOUNT_ERR;
    5979                 :           0 :                     goto exit_error;
    5980                 :             :                 }
    5981         [ #  # ]:           0 :                 for (i = 1; i <= num_iso_NoAuxBase; i++)
    5982                 :             :                 {
    5983                 :           0 :                     j = t_group_info->nIsotopicEndpointAtomNumber[i];
    5984   [ #  #  #  # ]:           0 :                     if (at_base[j].endpoint || !( at_base[j].cFlags & AT_FLAG_ISO_H_POINT ))
    5985                 :             :                     {
    5986                 :           0 :                         ret = CT_ISOCOUNT_ERR;
    5987                 :           0 :                         goto exit_error;
    5988                 :             :                     }
    5989                 :             :                 }
    5990                 :             :             }
    5991                 :             : 
    5992                 :             :             /* t-groups */
    5993                 :           0 :             num_iso_Base = 0;
    5994         [ #  # ]:           0 :             if (iso_exchg_atnos)
    5995                 :             :             {
    5996         [ #  # ]:           0 :                 for (i = num_atoms; i < num_at_tg; i++)
    5997                 :             :                 {
    5998                 :           0 :                     iso_sort_keyBase[i] = EMPTY_ISO_SORT_KEY; /* new mode: do not provide info about isotopic tautomeric H */
    5999                 :             :                 }
    6000                 :             :             }
    6001                 :             :             else
    6002                 :             :             {
    6003         [ #  # ]:           0 :                 for (i = num_atoms; i < num_at_tg; i++)
    6004                 :             :                 {
    6005                 :             :                     /* should not happen anymore */
    6006                 :           0 :                     m = i - num_atoms;
    6007         [ #  # ]:           0 :                     if ((iso_sort_key = t_group_info->t_group[m].iWeight)) /* djb-rwth: addressing LLVM warning */
    6008                 :             :                     {
    6009                 :             :                         /* old approach: each t-group has its own isotopic "weight" */
    6010                 :           0 :                         num_iso_Base++;
    6011                 :           0 :                         iso_sort_keyBase[i] = iso_sort_key;
    6012                 :             :                     }
    6013                 :             :                     else
    6014                 :             :                     {
    6015                 :           0 :                         iso_sort_keyBase[i] = EMPTY_ISO_SORT_KEY;
    6016                 :             :                     }
    6017                 :             :                 }
    6018                 :             :             }
    6019                 :             : 
    6020   [ #  #  #  # ]:           0 :             if (!num_iso_NoAuxBase && iso_exchg_atnos)
    6021                 :             :             {
    6022                 :             :                 /* all atoms that may exchange isotopic H are either tautomeric or not present */
    6023         [ #  # ]:           0 :                 inchi_free( iso_exchg_atnos );
    6024                 :           0 :                 iso_exchg_atnos = NULL;
    6025                 :           0 :                 len_iso_exchg_atnos = 0;
    6026                 :           0 :                 maxlen_iso_exchg_atnos = 0;
    6027                 :             :             }
    6028                 :             : 
    6029   [ #  #  #  #  :           0 :             if (!num_iso_NoTautH && !num_iso_Base && iso_sort_keyBase)
                   #  # ]
    6030                 :             :             {
    6031                 :             :                 /* no isotopic atoms present */
    6032         [ #  # ]:           0 :                 inchi_free( iso_sort_keyBase );
    6033                 :           0 :                 iso_sort_keyBase = NULL;
    6034                 :           0 :                 maxlen_iso_sort_keyBase = 0;
    6035                 :             :             }
    6036                 :             :             else
    6037                 :             :             {
    6038                 :           0 :                 len_iso_sort_keyBase = num_at_tg;
    6039                 :             :             }
    6040                 :             : 
    6041   [ #  #  #  # ]:           0 :             if (!iso_exchg_atnos && !iso_sort_keyBase)
    6042                 :             :             {
    6043                 :             :                 /* no isotopic part at all or only tautomeric groups */
    6044         [ #  # ]:           0 :                 inchi_free( nSymmRankBaseIso );        nSymmRankBaseIso = NULL;
    6045         [ #  # ]:           0 :                 inchi_free( nCanonRankBaseIso );       nCanonRankBaseIso = NULL;
    6046         [ #  # ]:           0 :                 inchi_free( nAtomNumberCanonBaseIso ); nAtomNumberCanonBaseIso = NULL;
    6047                 :             :             }
    6048                 :             :             else
    6049                 :             :             {
    6050                 :             :                 /* proceed with tautomeric isotopic canonicalization */
    6051                 :             :                 /* pointers */
    6052                 :           0 :                 pCD[iBase].LinearCT = NULL;
    6053                 :           0 :                 pCD[iBase].NumH = numH; /* num_atoms non-tautomeric H; num_tg pairs of H and (-) in t-groups */
    6054                 :           0 :                 pCD[iBase].NumHfixed = NULL;
    6055                 :           0 :                 pCD[iBase].iso_sort_key = iso_sort_keyBase;
    6056                 :           0 :                 pCD[iBase].iso_exchg_atnos = iso_exchg_atnos;
    6057                 :             : 
    6058                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6059                 :             :                 pCD[iBase].iso_sort_key_Hfixed = NULL;
    6060                 :             : #endif
    6061                 :             : 
    6062                 :             :                 /* variables - unchanged */
    6063                 :           0 :                 pCD[iBase].ulTimeOutTime = pBCN->ulTimeOutTime;
    6064                 :           0 :                 pCD[iBase].nMaxLenLinearCT = s[iBase].nLenCT + 1;
    6065                 :           0 :                 pCD[iBase].maxlenNumH = maxlenNumH;
    6066                 :             :                 /* return values & input/output */
    6067                 :           0 :                 pCD[iBase].nLenLinearCT = s[iBase].nLenCT;
    6068                 :           0 :                 pCD[iBase].nLenCTAtOnly = s[iBase].nLenCTAtOnly;
    6069                 :           0 :                 pCD[iBase].lenNumH = lenNumH /* = k */;
    6070                 :           0 :                 pCD[iBase].lenNumHfixed = 0;
    6071                 :           0 :                 pCD[iBase].len_iso_sort_key = len_iso_sort_keyBase;
    6072                 :           0 :                 pCD[iBase].maxlen_iso_sort_key = maxlen_iso_sort_keyBase;
    6073                 :           0 :                 pCD[iBase].len_iso_exchg_atnos = len_iso_exchg_atnos;
    6074                 :           0 :                 pCD[iBase].maxlen_iso_exchg_atnos = maxlen_iso_exchg_atnos;
    6075                 :             : 
    6076                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6077                 :             :                 pCD[iBase].len_iso_sort_key_Hfixed = 0;
    6078                 :             :                 pCD[iBase].maxlen_iso_sort_key_Hfixed = 0;
    6079                 :             : #endif
    6080                 :             : 
    6081                 :           0 :                 pCD[iBase].nAuxRank = NULL;
    6082                 :             : 
    6083   [ #  #  #  #  :           0 :                 if (num_iso_NoTautH || num_iso_Base || num_iso_NoAuxBase)
                   #  # ]
    6084                 :             :                 {
    6085                 :             :                     /* check whether we need actual canonicalization */
    6086                 :           0 :                     memset( nTempRank, 0, num_max * sizeof( nTempRank[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    6087         [ #  # ]:           0 :                     for (i = 0; i < num_at_tg; i++)
    6088                 :             :                     {
    6089         [ #  # ]:           0 :                         if (nTempRank[nSymmRankBase[i] - 1] < i)
    6090                 :             :                         {
    6091                 :           0 :                             nTempRank[nSymmRankBase[i] - 1] = i; /* greatest class representative */
    6092                 :             :                         }
    6093                 :             :                     }
    6094         [ #  # ]:           0 :                     for (i = 0; i < num_at_tg; i++)
    6095                 :             :                     {
    6096   [ #  #  #  #  :           0 :                         if (( iso_sort_keyBase ? ( iso_sort_keyBase[i] != iso_sort_keyBase[nTempRank[nSymmRankBase[i] - 1]] ) : 0 ) ||
                   #  # ]
    6097         [ #  # ]:           0 :                             ( iso_exchg_atnos ? ( iso_exchg_atnos[i] != iso_exchg_atnos[nTempRank[nSymmRankBase[i] - 1]] ) : 0 ))
    6098                 :             :                         {
    6099                 :           0 :                             pCD[iBase].nCanonFlags |= CANON_FLAG_ISO_TAUT_DIFF;
    6100                 :           0 :                             break; /* atoms so far found to be equivalent have different number of H; the canonicalization is needed */
    6101                 :             :                         }
    6102                 :             :                     }
    6103                 :             :                 }
    6104                 :             :                 else
    6105                 :             :                 {
    6106                 :           0 :                     i = num_at_tg; /* should not happen */
    6107                 :             :                 }
    6108                 :             : 
    6109                 :             :                 /* i = 0; *//* debug: force to call the canonicalization */
    6110                 :             : 
    6111         [ #  # ]:           0 :                 if (i < num_at_tg)
    6112                 :             :                 {
    6113                 :             :                     /* we need canonicalization */
    6114                 :             :                     /* get aux canonical ranking of the structure with isotopic non-tautomeric H */
    6115                 :             : 
    6116                 :             : #if ( USE_AUX_RANKING == 1 )
    6117                 :             :                 /* refine no-taut-H partition according to non-taut H + t-groups isotopic distribution */
    6118                 :           0 :                     memset( pAtomInvariantAux, 0, num_max * sizeof( pAtomInvariantAux[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    6119         [ #  # ]:           0 :                     for (i = 0; i < num_at_tg; i++)
    6120                 :             :                     {
    6121                 :           0 :                         pAtomInvariantAux[i].val[0] = nSymmRankBase[i];
    6122         [ #  # ]:           0 :                         pAtomInvariantAux[i].iso_sort_key = iso_sort_keyBase ? iso_sort_keyBase[i] : 0; /* additional differentiation */
    6123         [ #  # ]:           0 :                         pAtomInvariantAux[i].iso_aux_key = iso_exchg_atnos ? iso_exchg_atnos[i] : 0;
    6124                 :             :                     }
    6125                 :             :                     /* initial ranks for non-taut H isotopic distribution */
    6126                 :           0 :                     nNumCurrRanks = SetInitialRanks2( num_at_tg, pAtomInvariantAux, nRankAux, nAtomNumberAux, pCG );
    6127                 :             :                     /* make equitable, not a digraph procedure */
    6128                 :           0 :                     nNumCurrRanks = DifferentiateRanks2( pCG, num_at_tg, NeighList[TAUT_YES],
    6129                 :             :                                                         nNumCurrRanks, nRankAux,
    6130                 :             :                                                         nTempRank, nAtomNumberAux, &lCount, 0 /* 0 means first use qsort */ ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    6131                 :             :                     /* to accelerate do not call CanonGraph() to find really equivalent atoms */
    6132                 :           0 :                     pCD[iBase].nAuxRank = nRankAux;
    6133                 :             : #endif
    6134                 :             : 
    6135                 :           0 :                     ret = CanonGraph06( ic, pCG, num_atoms, num_at_tg, num_max, 1 /* digraph */,
    6136                 :           0 :                                         NeighList[TAUT_YES], (Partition *) pBCN->pRankStack,
    6137                 :             :                                         nSymmRankBaseIso, nCanonRankBaseIso, nAtomNumberCanonBaseIso,
    6138                 :           0 :                                         pCD + iBase, pCC, &Ct_Base, &Ct_BaseIso, LargeMolecules );
    6139         [ #  # ]:           0 :                     if (ret < 0)
    6140                 :             :                     {
    6141                 :           0 :                         goto exit_error;
    6142                 :             :                     }
    6143                 :             :                     /* in case of a tautomeric structure the final results are in:
    6144                 :             : 
    6145                 :             :                                nSymmRankBaseIso
    6146                 :             :                                nCanonRankBaseIso
    6147                 :             :                                nAtomNumberCanonBaseIso
    6148                 :             :                                Ct_BaseIso
    6149                 :             :                                iso_sort_keyBase (original isotopic atom & t-group positions)
    6150                 :             :                                Ct_BaseIso->iso_exchg_atnos: 0=>can exchange isotopic H, including tautomeric atoms
    6151                 :             :                                iso_exchg_atnos            : same, in order of t_group_info->nIsotopicEndpointAtomNumber[]
    6152                 :             :                     */
    6153                 :             :                 }
    6154                 :             :                 else
    6155                 :             :                 {
    6156                 :             :                     /* copy the results of the previous (no taut H) canonicalization */
    6157                 :             :                     /* in this case numHNoTautH[] is not needed for the next canonicalization(s) */
    6158   [ #  #  #  # ]:           0 :                     if (( Ct_Temp = (ConTable *) inchi_calloc( 1, sizeof( *Ct_Temp ) ) ) &&
    6159                 :           0 :                          CTableCreate( Ct_Temp, num_atoms, pCD + iBase ))
    6160                 :             :                     {
    6161                 :           0 :                         CtFullCopy( Ct_Temp, Ct_Base );
    6162                 :             :                         /* since Ct_Base does not have Ct_Base->iso_sort_key we
    6163                 :             :                            have to fill out Ct_Temp->iso_sort_key separately */
    6164         [ #  # ]:           0 :                         if (iso_sort_keyBase)
    6165                 :             :                         {
    6166         [ #  # ]:           0 :                             for (i = 0; i < num_at_tg; i++)
    6167                 :             :                             {
    6168                 :           0 :                                 Ct_Temp->iso_sort_key[nCanonRankBase[i] - 1] = iso_sort_keyBase[i];
    6169                 :             :                             }
    6170                 :           0 :                             Ct_Temp->len_iso_sort_key = num_at_tg;
    6171                 :             :                         }
    6172                 :             :                         else
    6173                 :             :                         {
    6174                 :           0 :                             Ct_Temp->len_iso_sort_key = 0;
    6175                 :             :                         }
    6176         [ #  # ]:           0 :                         if (iso_exchg_atnos)
    6177                 :             :                         {
    6178         [ #  # ]:           0 :                             for (i = 0; i < num_atoms; i++)
    6179                 :             :                             {
    6180                 :           0 :                                 Ct_Temp->iso_exchg_atnos[nCanonRankBase[i] - 1] = iso_exchg_atnos[i];
    6181                 :             :                             }
    6182                 :           0 :                             Ct_Temp->len_iso_exchg_atnos = num_at_tg;
    6183                 :             :                         }
    6184                 :             :                         else
    6185                 :             :                         {
    6186                 :           0 :                             Ct_Temp->len_iso_exchg_atnos = 0;
    6187                 :             :                         }
    6188                 :             :                     }
    6189                 :             :                     else
    6190                 :             :                     {
    6191                 :           0 :                         goto exit_error_alloc;
    6192                 :             :                     }
    6193                 :           0 :                     Ct_BaseIso = Ct_Temp;
    6194                 :           0 :                     Ct_Temp = NULL;
    6195                 :           0 :                     memcpy(nSymmRankBaseIso, nSymmRankBase, num_at_tg * sizeof(nSymmRankBaseIso[0]));
    6196                 :           0 :                     memcpy(nCanonRankBaseIso, nCanonRankBase, num_at_tg * sizeof(nCanonRankBaseIso[0]));
    6197                 :           0 :                     memcpy(nAtomNumberCanonBaseIso, nAtomNumberCanonBase, num_at_tg * sizeof(nAtomNumberCanonBaseIso[0]));
    6198                 :             :                 }
    6199                 :             :                 /* in case of non-tautomeric component this is the final result */
    6200                 :             :                 /* i = CtFullCompare( Ct_BaseIso, Ct_Temp, num_at_tg, 0, 0 );*/
    6201                 :             : 
    6202                 :           0 :                 t_group_info->bIgnoreIsotopic = 1;
    6203                 :             :             }
    6204                 :             :         }
    6205                 :             :     }
    6206                 :             : 
    6207                 :             :     /**********************************************************************************/
    6208                 :             :     /* get "fixed H" canonical numbering, connection table, and equivalence partition */
    6209                 :             :     /**********************************************************************************/
    6210                 :             : 
    6211   [ +  +  -  + ]:         161 :     if (bReqTaut && bReqNonTaut)
    6212                 :             :     {
    6213                 :           0 :         maxlenNumHfixed = num_atoms + 1;
    6214                 :           0 :         nSymmRankFixH = (AT_RANK *) inchi_calloc( num_max, sizeof( nSymmRankFixH[0] ) );
    6215                 :           0 :         nCanonRankFixH = (AT_RANK *) inchi_calloc( num_max, sizeof( nCanonRankFixH[0] ) );
    6216                 :           0 :         nAtomNumberCanonFixH = (AT_NUMB *) inchi_calloc( num_max, sizeof( nAtomNumberCanonFixH[0] ) );
    6217                 :           0 :         NumHfixed = (NUM_H *) inchi_calloc( maxlenNumHfixed, sizeof( NumHfixed[0] ) );
    6218   [ #  #  #  #  :           0 :         if (!NumHfixed || !nSymmRankFixH || !nCanonRankFixH || !nAtomNumberCanonFixH)
             #  #  #  # ]
    6219                 :             :         {
    6220                 :           0 :             goto exit_error_alloc;
    6221                 :             :         }
    6222         [ #  # ]:           0 :         for (i = 0; i < num_atoms; i++)
    6223                 :             :         {
    6224                 :             :             /* fixed and non-tautomeric H different in taut and non-taut structures */
    6225                 :             : 
    6226         [ #  # ]:           0 :             if (at_base[i].endpoint)
    6227                 :             :             {
    6228         [ #  # ]:           0 :                 NumHfixed[i] = at_other[i].num_H ? at_other[i].num_H + BASE_H_NUMBER : EMPTY_H_NUMBER;
    6229                 :             :             }
    6230         [ #  # ]:           0 :             else if (at_other[i].num_H != at_base[i].num_H)
    6231                 :             :             {
    6232                 :           0 :                 NumHfixed[i] = (NUM_H) at_other[i].num_H - (NUM_H) at_base[i].num_H + BASE_H_NUMBER;
    6233                 :             :             }
    6234                 :             :             else
    6235                 :             :             {
    6236                 :           0 :                 NumHfixed[i] = EMPTY_H_NUMBER;
    6237                 :             :             }
    6238                 :             :         }
    6239                 :             : 
    6240                 :             :         /* pointers */
    6241                 :           0 :         pCD[iOther].LinearCT = NULL; /* LinearCT; */
    6242                 :           0 :         pCD[iOther].NumH = numHNoTautH;
    6243                 :           0 :         pCD[iOther].NumHfixed = NumHfixed;/* variables - unchanged */
    6244                 :           0 :         pCD[iOther].iso_sort_key = NULL;
    6245                 :           0 :         pCD[iOther].iso_exchg_atnos = NULL;
    6246                 :             : 
    6247                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6248                 :             :         pCD[iOther].iso_sort_key_Hfixed = NULL;
    6249                 :             : #endif
    6250                 :             : 
    6251                 :           0 :         pCD[iOther].ulTimeOutTime = pBCN->ulTimeOutTime;
    6252                 :           0 :         pCD[iOther].nMaxLenLinearCT = s[iOther].nLenCTAtOnly + 1;
    6253                 :           0 :         pCD[iOther].maxlenNumH = maxlenNumHNoTautH;
    6254                 :           0 :         pCD[iOther].maxlenNumHfixed = maxlenNumHfixed;
    6255                 :             :         /* return values & input/output */
    6256                 :           0 :         pCD[iOther].nLenLinearCT = s[iOther].nLenCTAtOnly;
    6257                 :           0 :         pCD[iOther].nLenCTAtOnly = s[iOther].nLenCTAtOnly;
    6258                 :           0 :         pCD[iOther].lenNumH = num_atoms; /* djb-rwth: removing redundant code */
    6259                 :           0 :         pCD[iOther].lenNumHfixed = num_atoms;
    6260                 :           0 :         pCD[iOther].len_iso_sort_key = 0;
    6261                 :           0 :         pCD[iOther].maxlen_iso_sort_key = 0;
    6262                 :           0 :         pCD[iOther].len_iso_exchg_atnos = 0;
    6263                 :           0 :         pCD[iOther].maxlen_iso_exchg_atnos = 0;
    6264                 :             : 
    6265                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6266                 :             :         pCD[iOther].len_iso_sort_key_Hfixed = 0;
    6267                 :             :         pCD[iOther].maxlen_iso_sort_key_Hfixed = 0;
    6268                 :             : #endif
    6269                 :             : 
    6270                 :           0 :         pCD[iOther].nAuxRank = NULL;
    6271                 :             : 
    6272                 :             : #if ( USE_AUX_RANKING == 1 )
    6273         [ #  # ]:           0 :         if (!nRankAux)
    6274                 :             :         {
    6275                 :           0 :             nRankAux = (AT_RANK *) inchi_calloc( num_max, sizeof( nRankAux[0] ) );
    6276                 :             :         }
    6277         [ #  # ]:           0 :         if (!nAtomNumberAux)
    6278                 :             :         {
    6279                 :           0 :             nAtomNumberAux = (AT_NUMB *) inchi_calloc( num_max, sizeof( nAtomNumberAux[0] ) );
    6280                 :             :         }
    6281         [ #  # ]:           0 :         if (!pAtomInvariantAux)
    6282                 :             :         {
    6283                 :           0 :             pAtomInvariantAux = (ATOM_INVARIANT2 *) inchi_malloc( num_max * sizeof( pAtomInvariantAux[0] ) );
    6284                 :             :         }
    6285   [ #  #  #  #  :           0 :         if (!nRankAux || !nAtomNumberAux || !pAtomInvariantAux)
                   #  # ]
    6286                 :             :         {
    6287                 :           0 :             goto exit_error_alloc;
    6288                 :             :         }
    6289                 :             : 
    6290                 :             :         /* refine no-H partition according to non-taut H distribution */
    6291                 :           0 :         memset( pAtomInvariantAux, 0, num_max * sizeof( pAtomInvariantAux[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    6292         [ #  # ]:           0 :         for (i = 0; i < num_atoms; i++)
    6293                 :             :         {
    6294                 :           0 :             pAtomInvariantAux[i].val[0] = nSymmRankBase[i];
    6295                 :           0 :             pAtomInvariantAux[i].val[1] = NumHfixed[i]; /* additional differentiation */
    6296                 :             :         }
    6297                 :             : 
    6298                 :             :         /* initial ranks for t-group(s) */
    6299                 :           0 :         nNumCurrRanks = SetInitialRanks2( num_atoms, pAtomInvariantAux, nRankAux, nAtomNumberAux, pCG );
    6300                 :             : 
    6301                 :             :         /* make equitable, digraph procedure */
    6302                 :           0 :         nNumCurrRanks = DifferentiateRanks2( pCG, num_atoms, NeighList[TAUT_NON],
    6303                 :             :                                             nNumCurrRanks, nRankAux,
    6304                 :             :                                             nTempRank, nAtomNumberAux, &lCount, 0 /* 0 means use qsort */ ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    6305                 :             :         /* to accelerate do not call CanonGraph() to find really equivalent atoms */
    6306                 :           0 :         pCD[iOther].nAuxRank = nRankAux;
    6307                 :             : #endif
    6308                 :             : 
    6309                 :           0 :         ret = CanonGraph07( ic, pCG, num_atoms, num_atoms, num_max, 0,
    6310                 :           0 :                             NeighList[TAUT_NON], (Partition *) pBCN->pRankStack,
    6311                 :             :                             nSymmRankFixH, nCanonRankFixH, nAtomNumberCanonFixH,
    6312                 :           0 :                             pCD + iOther, pCC, &Ct_NoTautH, &Ct_FixH, LargeMolecules );
    6313         [ #  # ]:           0 :         if (ret < 0)
    6314                 :             :         {
    6315                 :           0 :             goto exit_error;
    6316                 :             :         }
    6317                 :             : 
    6318                 :             :         /*******************************************************************************************/
    6319                 :             :         /* get "fixed H" isotopic canonical numbering, connection table, and equivalence partition */
    6320                 :             :         /*******************************************************************************************/
    6321   [ #  #  #  # ]:           0 :         iflag = (s[iBase].num_isotopic_atoms && !s[iBase].bIgnoreIsotopic) ||
    6322   [ #  #  #  # ]:           0 :             (s[iBase].bHasIsotopicTautGroups && !bTautIgnoreIsotopic); /* djb-rwth: addressing LLVM warning */
    6323         [ #  # ]:           0 :         if (bFixIsoFixedH) /* #if ( FIX_ISO_FIXEDH_BUG == 1 )  */
    6324                 :             :              /* fix bug when iso H was removed as a proton and fixed-H isotopic layer is missing -  2008-09-24 DT*/
    6325                 :             :         {
    6326   [ #  #  #  #  :           0 :             iflag = iflag || (s[iOther].num_isotopic_atoms && !s[iOther].bIgnoreIsotopic); /* djb-rwth: addressing LLVM warning */
                   #  # ]
    6327                 :             :         }
    6328         [ #  # ]:           0 :         if (iflag)
    6329                 :             :         {
    6330                 :             : 
    6331                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6332                 :             :             maxlen_iso_sort_key_Hfixed =
    6333                 :             : #endif
    6334                 :           0 :             maxlen_iso_sort_key_NoTautH = num_atoms + 1;
    6335                 :           0 :             nSymmRankFixHIso = (AT_RANK *) inchi_calloc( num_max, sizeof( nSymmRankFixHIso[0] ) );
    6336                 :           0 :             nCanonRankFixHIso = (AT_RANK *) inchi_calloc( num_max, sizeof( nCanonRankFixHIso[0] ) );
    6337                 :           0 :             nAtomNumberCanonFixHIso = (AT_NUMB *) inchi_calloc( num_max, sizeof( nAtomNumberCanonFixHIso[0] ) );
    6338                 :             : 
    6339                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6340                 :             :             iso_sort_key_Hfixed = (AT_ISO_SORT_KEY *) inchi_calloc( maxlen_iso_sort_key_Hfixed, sizeof( iso_sort_key_Hfixed[0] ) );
    6341                 :             : #endif
    6342                 :             : 
    6343                 :           0 :             iso_sort_key_NoTautH = (AT_ISO_SORT_KEY *) inchi_calloc( maxlen_iso_sort_key_NoTautH, sizeof( iso_sort_key_NoTautH[0] ) );
    6344                 :             : 
    6345   [ #  #  #  #  :           0 :             if (!nSymmRankFixHIso || !nCanonRankFixHIso || !nAtomNumberCanonFixHIso ||
             #  #  #  # ]
    6346                 :             : 
    6347                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6348                 :             :                  !iso_sort_key_Hfixed ||
    6349                 :             : #endif
    6350                 :             : 
    6351                 :             :                  !iso_sort_key_NoTautH)
    6352                 :             :             {
    6353                 :           0 :                 goto exit_error_alloc;
    6354                 :             :             }
    6355                 :             : 
    6356                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6357                 :             :             /* fill out isotopic non-tautomeric keys */
    6358                 :             :             for (i = 0; i < num_atoms; i++)
    6359                 :             :             {
    6360                 :             :                 if (at_base[i].endpoint)
    6361                 :             :                 {
    6362                 :             :                     iso_sort_key = make_iso_sort_key( at_base[i].iso_atw_diff, 0, 0, 0 );
    6363                 :             :                     iso_sort_key2 = make_iso_sort_key( 0, at_base[i].num_iso_H[0], at_base[i].num_iso_H[1], at_base[i].num_iso_H[2] );
    6364                 :             :                 }
    6365                 :             :                 else
    6366                 :             :                 {
    6367                 :             :                     iso_sort_key = make_iso_sort_key( at_base[i].iso_atw_diff, at_base[i].num_iso_H[0], at_base[i].num_iso_H[1], at_base[i].num_iso_H[2] );
    6368                 :             :                     iso_sort_key2 = 0;
    6369                 :             :                 }
    6370                 :             :                 if (iso_sort_key)
    6371                 :             :                 {
    6372                 :             :                     iso_sort_key_NoTautH[i] = iso_sort_key;
    6373                 :             :                     num_iso_NoTautH++;
    6374                 :             :                 }
    6375                 :             :                 else
    6376                 :             :                 {
    6377                 :             :                     iso_sort_key_NoTautH[i] = EMPTY_ISO_SORT_KEY;
    6378                 :             :                 }
    6379                 :             :                 if (iso_sort_key2)
    6380                 :             :                 {
    6381                 :             :                     num_iso_Hfixed++;
    6382                 :             :                     iso_sort_key_Hfixed[i] = iso_sort_key2;
    6383                 :             :                 }
    6384                 :             :                 else
    6385                 :             :                 {
    6386                 :             :                     iso_sort_key_Hfixed[i] = EMPTY_ISO_SORT_KEY;
    6387                 :             :                 }
    6388                 :             :             }
    6389                 :             : #else
    6390                 :             :             /* fill out isotopic non-tautomeric keys */
    6391         [ #  # ]:           0 :             for (i = 0; i < num_atoms; i++)
    6392                 :             :             {
    6393                 :             : 
    6394         [ #  # ]:           0 :                 if (bFixIsoFixedH) /* #if ( FIX_ISO_FIXEDH_BUG == 1 )  */
    6395                 :             :                 {
    6396                 :             :                     /* fix bug when iso H was removed as a proton and fixed-H isotopic layer is missing -  2008-09-24 DT*/
    6397         [ #  # ]:           0 :                     if (at_other)
    6398                 :             :                     {
    6399                 :           0 :                         iso_sort_key = make_iso_sort_key( at_other[i].iso_atw_diff, at_other[i].num_iso_H[0], at_other[i].num_iso_H[1], at_other[i].num_iso_H[2] );
    6400                 :             :                     }
    6401                 :             :                     else
    6402                 :             :                     {
    6403                 :           0 :                         iso_sort_key = make_iso_sort_key( at_base[i].iso_atw_diff, at_base[i].num_iso_H[0], at_base[i].num_iso_H[1], at_base[i].num_iso_H[2] );
    6404                 :             :                     }
    6405                 :             :                 }
    6406                 :             :                 else
    6407                 :           0 :                     iso_sort_key = make_iso_sort_key( at_base[i].iso_atw_diff, at_base[i].num_iso_H[0], at_base[i].num_iso_H[1], at_base[i].num_iso_H[2] );
    6408                 :             : 
    6409         [ #  # ]:           0 :                 if (iso_sort_key)
    6410                 :             :                 {
    6411                 :           0 :                     iso_sort_key_NoTautH[i] = iso_sort_key;
    6412                 :           0 :                     num_iso_NoTautH++;
    6413                 :             :                 }
    6414                 :             :                 else
    6415                 :             :                 {
    6416                 :           0 :                     iso_sort_key_NoTautH[i] = EMPTY_ISO_SORT_KEY;
    6417                 :             :                 }
    6418                 :             :             }
    6419                 :             : #endif
    6420                 :             : 
    6421                 :             :             /* pointers */
    6422                 :           0 :             pCD[iOther].LinearCT = NULL; /* LinearCT; */
    6423                 :           0 :             pCD[iOther].NumH = numHNoTautH;
    6424                 :           0 :             pCD[iOther].NumHfixed = NumHfixed;/* variables - unchanged */
    6425                 :           0 :             pCD[iOther].iso_sort_key = iso_sort_key_NoTautH;
    6426                 :           0 :             pCD[iOther].iso_exchg_atnos = NULL;
    6427                 :             : 
    6428                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6429                 :             :             pCD[iOther].iso_sort_key_Hfixed = iso_sort_key_Hfixed;
    6430                 :             : #endif
    6431                 :             : 
    6432                 :           0 :             pCD[iOther].ulTimeOutTime = pBCN->ulTimeOutTime;
    6433                 :           0 :             pCD[iOther].nMaxLenLinearCT = s[iOther].nLenCTAtOnly + 1;
    6434                 :           0 :             pCD[iOther].maxlenNumH = maxlenNumHNoTautH;
    6435                 :           0 :             pCD[iOther].maxlenNumHfixed = maxlenNumHfixed;
    6436                 :             :             /* return values & input/output */
    6437                 :           0 :             pCD[iOther].nLenLinearCT = s[iOther].nLenCTAtOnly;
    6438                 :           0 :             pCD[iOther].nLenCTAtOnly = s[iOther].nLenCTAtOnly;
    6439                 :           0 :             pCD[iOther].lenNumH = num_atoms; /* djb-rwth: removing redundant code */
    6440                 :           0 :             pCD[iOther].lenNumHfixed = num_atoms;
    6441                 :           0 :             pCD[iOther].len_iso_sort_key = len_iso_sort_key_NoTautH = num_atoms;
    6442                 :           0 :             pCD[iOther].maxlen_iso_sort_key = maxlen_iso_sort_key_NoTautH;
    6443                 :           0 :             pCD[iOther].len_iso_exchg_atnos = 0;
    6444                 :           0 :             pCD[iOther].maxlen_iso_exchg_atnos = 0;
    6445                 :             : 
    6446                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6447                 :             :             pCD[iOther].len_iso_sort_key_Hfixed = len_iso_sort_key_Hfixed = num_atoms;
    6448                 :             :             pCD[iOther].maxlen_iso_sort_key_Hfixed = maxlen_iso_sort_key_Hfixed;
    6449                 :             : #endif
    6450                 :             : 
    6451                 :           0 :             pCD[iOther].nAuxRank = NULL;
    6452                 :             : 
    6453                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6454                 :             :             if (num_iso_Hfixed || num_iso_NoTautH)
    6455                 :             : #else
    6456         [ #  # ]:           0 :             if (num_iso_NoTautH)
    6457                 :             : #endif
    6458                 :             : 
    6459                 :             :             {
    6460                 :             :                 /* check whether we need NoTautH cononicalization */
    6461                 :           0 :                 memset( nTempRank, 0, num_max * sizeof( nTempRank[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    6462         [ #  # ]:           0 :                 for (i = 0; i < num_atoms; i++)
    6463                 :             :                 {
    6464         [ #  # ]:           0 :                     if (nTempRank[nSymmRankFixH[i] - 1] < i)
    6465                 :             :                     {
    6466                 :           0 :                         nTempRank[nSymmRankFixH[i] - 1] = i; /* greatest class representative */
    6467                 :             :                     }
    6468                 :             :                 }
    6469         [ #  # ]:           0 :                 for (i = 0; i < num_atoms; i++)
    6470                 :             :                 {
    6471                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6472                 :             :                     if (iso_sort_key_Hfixed[i] != iso_sort_key_Hfixed[nTempRank[nSymmRankFixH[i] - 1]])
    6473                 :             :                         break;
    6474                 :             : #endif
    6475         [ #  # ]:           0 :                     if (iso_sort_key_NoTautH[i] != iso_sort_key_NoTautH[nTempRank[nSymmRankFixH[i] - 1]])
    6476                 :           0 :                         break; /* atoms so far found to be equivalent have different isotopic shifts; the canonicalization is needed */
    6477                 :             :                 }
    6478                 :             :             }
    6479                 :             :             else
    6480                 :             :             {
    6481                 :           0 :                 i = num_atoms; /* should not happen */
    6482                 :             :             }
    6483                 :             : 
    6484                 :             :             /* i = 0; *//* debug: force to call the canonicalization */
    6485                 :             : 
    6486         [ #  # ]:           0 :             if (i < num_atoms)
    6487                 :             :             {
    6488                 :           0 :                 pCD[iOther].nCanonFlags |= CANON_FLAG_ISO_FIXED_H_DIFF;
    6489                 :             :                 /* we need canonicalization */
    6490                 :             :                 /* get aux canonical ranking of the structure with isotopic non-tautomeric H */
    6491                 :             : 
    6492                 :             : #if ( USE_AUX_RANKING == 1 )
    6493                 :             :                 /* refine fixed-taut-H partition according to the isotopic distribution */
    6494                 :           0 :                 memset( pAtomInvariantAux, 0, num_max * sizeof( pAtomInvariantAux[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    6495         [ #  # ]:           0 :                 for (i = 0; i < num_atoms; i++)
    6496                 :             :                 {
    6497                 :           0 :                     pAtomInvariantAux[i].val[0] = nSymmRankFixH[i];
    6498                 :             : 
    6499                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6500                 :             :                     iso_sort_key = 0;
    6501                 :             :                     if (iso_sort_key_NoTautH[i] != EMPTY_ISO_SORT_KEY)
    6502                 :             :                         iso_sort_key |= iso_sort_key_NoTautH[i];
    6503                 :             :                     if (iso_sort_key_Hfixed[i] != EMPTY_ISO_SORT_KEY)
    6504                 :             :                         iso_sort_key |= iso_sort_key_Hfixed[i];
    6505                 :             :                     if (!iso_sort_key)
    6506                 :             :                         iso_sort_key = EMPTY_ISO_SORT_KEY;
    6507                 :             : #else
    6508                 :           0 :                     iso_sort_key = iso_sort_key_NoTautH[i];
    6509                 :             : #endif
    6510                 :             : 
    6511                 :           0 :                     pAtomInvariantAux[i].iso_sort_key = iso_sort_key; /* additional differentiation */
    6512                 :             :                 }
    6513                 :             : 
    6514                 :             :                 /* initial ranks for non-taut H isotopic distribution */
    6515                 :           0 :                 nNumCurrRanks = SetInitialRanks2( num_atoms, pAtomInvariantAux, nRankAux, nAtomNumberAux, pCG );
    6516                 :             :                 /* make equitable, digraph procedure */
    6517                 :           0 :                 nNumCurrRanks = DifferentiateRanks2( pCG, num_atoms, NeighList[TAUT_NON],
    6518                 :             :                                                     nNumCurrRanks, nRankAux,
    6519                 :             :                                                     nTempRank, nAtomNumberAux, &lCount, 0 /* 0 means use qsort */ ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    6520                 :             : 
    6521                 :             :                 /* to accelerate do not call CanonGraph() to find really equivalent atoms */
    6522                 :           0 :                 pCD[iOther].nAuxRank = nRankAux;
    6523                 :             : #endif
    6524                 :             : 
    6525                 :           0 :                 ret = CanonGraph08( ic, pCG, num_atoms, num_atoms, num_max, 1 /* digraph?? was 0 */,
    6526                 :           0 :                                     NeighList[TAUT_NON], (Partition *) pBCN->pRankStack,
    6527                 :             :                                     nSymmRankFixHIso, nCanonRankFixHIso, nAtomNumberCanonFixHIso,
    6528                 :           0 :                                     pCD + iOther, pCC, &Ct_FixH, &Ct_FixHIso, LargeMolecules );
    6529         [ #  # ]:           0 :                 if (ret < 0)
    6530                 :             :                 {
    6531                 :           0 :                     goto exit_error;
    6532                 :             :                 }
    6533                 :             :                 /* in case of non-tautomeric structure the final results are in:
    6534                 :             : 
    6535                 :             :                            nSymmRankFixHIso
    6536                 :             :                            nCanonRankFixHIso
    6537                 :             :                            nAtomNumberCanonFixHIso
    6538                 :             :                            Ct_FixHIso
    6539                 :             :                            iso_sort_keyBase     ([0..num_atoms] original isotopic atom positions)
    6540                 :             :                            iso_sort_key_Hfixed  (original fixed tautomeric H distribution)
    6541                 :             :                 */
    6542                 :             :             }
    6543                 :             :             else
    6544                 :             :             {
    6545                 :             :                 /* copy the results of the previous (no taut H) canonicalization */
    6546                 :             :                 /* in this case numHNoTautH[] is not needed for the next canonicalization(s) */
    6547   [ #  #  #  # ]:           0 :                 if (( Ct_Temp = (ConTable *) inchi_calloc( 1, sizeof( *Ct_Temp ) ) ) &&
    6548                 :           0 :                      CTableCreate( Ct_Temp, num_atoms, pCD + iOther ))
    6549                 :             :                 {
    6550                 :           0 :                     CtFullCopy( Ct_Temp, Ct_FixH );
    6551                 :             :                     /* since Ct_FixH does not have Ct_FixH->iso_sort_key and Ct_FixH->iso_sort_key_Hfixed we
    6552                 :             :                        have to fill out Ct_Temp->iso_sort_key and Ct_Temp->iso_sort_key_Hfixed separately */
    6553         [ #  # ]:           0 :                     for (i = 0; i < num_atoms; i++)
    6554                 :             :                     {
    6555                 :           0 :                         Ct_Temp->iso_sort_key[nCanonRankFixH[i] - 1] = iso_sort_key_NoTautH[i];
    6556                 :             : 
    6557                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6558                 :             :                         Ct_Temp->iso_sort_key_Hfixed[nCanonRankFixH[i] - 1] = iso_sort_key_Hfixed[i];
    6559                 :             : #endif
    6560                 :             :                     }
    6561                 :           0 :                     Ct_Temp->len_iso_sort_key = num_atoms;
    6562                 :             : 
    6563                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6564                 :             :                     Ct_Temp->len_iso_sort_key_Hfixed = num_atoms;
    6565                 :             : #endif
    6566                 :             : 
    6567                 :             :                     /*Ct_Temp->lenNumH = num_atoms;*/
    6568                 :             :                 }
    6569                 :             :                 else
    6570                 :             :                 {
    6571                 :           0 :                     goto exit_error_alloc;
    6572                 :             :                 }
    6573                 :           0 :                 Ct_FixHIso = Ct_Temp;
    6574                 :           0 :                 Ct_Temp = NULL;
    6575                 :           0 :                 memcpy(nSymmRankFixHIso, nSymmRankFixH, num_atoms * sizeof(nSymmRankFixHIso[0]));
    6576                 :           0 :                 memcpy(nCanonRankFixHIso, nCanonRankFixH, num_atoms * sizeof(nCanonRankFixHIso[0]));
    6577                 :           0 :                 memcpy(nAtomNumberCanonFixHIso, nAtomNumberCanonFixH, num_atoms * sizeof(nAtomNumberCanonFixHIso[0]));
    6578                 :             :             }
    6579                 :             :             /* in case of non-tautomeric component this is the final result */
    6580                 :             :             /* i = CtFullCompare( Ct_NoTautHIso, Ct_Temp, num_atoms, 0, 0 );*/
    6581                 :             :         }
    6582                 :             :     } /* "fixed H" canonical numbering */
    6583                 :             : 
    6584                 :             : 
    6585                 :             :     /* consistency check: compare canonical connection tables, H-atoms, isotopic H & taut groups */
    6586                 :         161 :     ret = 0;
    6587   [ +  -  -  + ]:         161 :     ret |= ( Ct_NoH->lenCt != Ct_NoTautH->lenCt ) || memcmp( Ct_NoH->Ctbl, Ct_NoTautH->Ctbl, Ct_NoH->lenCt * sizeof( Ct_NoH->Ctbl[0] ) );
    6588         [ +  + ]:         161 :     if (bReqTaut)
    6589                 :             :     {
    6590         [ -  + ]:          14 :         if (Ct_FixH)
    6591                 :             :         {
    6592   [ #  #  #  # ]:           0 :             ret |= ( Ct_NoTautH->lenCt != Ct_FixH->lenCt ) || memcmp( Ct_NoTautH->Ctbl, Ct_FixH->Ctbl, Ct_NoTautH->lenCt * sizeof( Ct_NoTautH->Ctbl[0] ) );
    6593   [ #  #  #  # ]:           0 :             ret |= ( Ct_NoTautH->lenNumH != Ct_FixH->lenNumH ) || memcmp( Ct_NoTautH->NumH, Ct_FixH->NumH, Ct_NoTautH->lenNumH * sizeof( Ct_Base->NumH[0] ) );
    6594                 :             :         }
    6595   [ +  -  -  + ]:          14 :         ret |= ( Ct_NoTautH->lenCt > Ct_Base->lenCt ) || memcmp( Ct_NoTautH->Ctbl, Ct_Base->Ctbl, Ct_NoTautH->lenCt * sizeof( Ct_NoTautH->Ctbl[0] ) );
    6596   [ +  -  -  + ]:          14 :         ret |= ( Ct_NoTautH->lenNumH > Ct_Base->lenNumH ) || memcmp( Ct_NoTautH->NumH, Ct_Base->NumH, Ct_NoTautH->lenNumH * sizeof( Ct_Base->NumH[0] ) );
    6597                 :             :     }
    6598                 :             : 
    6599                 :             :     /* isotopic canonicalization */
    6600         [ -  + ]:         161 :     if (Ct_NoTautHIso)
    6601                 :             :     {
    6602   [ #  #  #  # ]:           0 :         ret |= ( Ct_NoH->lenCt != Ct_NoTautHIso->lenCt ) || memcmp( Ct_NoH->Ctbl, Ct_NoTautHIso->Ctbl, Ct_NoH->lenCt * sizeof( Ct_NoH->Ctbl[0] ) );
    6603   [ #  #  #  # ]:           0 :         ret |= ( Ct_NoTautH->lenNumH != Ct_NoTautHIso->lenNumH ) || memcmp( Ct_NoTautH->NumH, Ct_NoTautHIso->NumH, Ct_NoTautH->lenNumH * sizeof( Ct_Base->NumH[0] ) );
    6604                 :             :     }
    6605         [ -  + ]:         161 :     else if (Ct_BaseIso)
    6606                 :             :     {
    6607   [ #  #  #  # ]:           0 :         ret |= ( Ct_BaseIso->lenCt != Ct_Base->lenCt ) || memcmp( Ct_BaseIso->Ctbl, Ct_Base->Ctbl, Ct_BaseIso->lenCt * sizeof( Ct_BaseIso->Ctbl[0] ) );
    6608   [ #  #  #  # ]:           0 :         ret |= ( Ct_BaseIso->lenNumH != Ct_Base->lenNumH ) || memcmp( Ct_BaseIso->NumH, Ct_Base->NumH, Ct_BaseIso->lenNumH * sizeof( Ct_BaseIso->NumH[0] ) );
    6609         [ #  # ]:           0 :         if (Ct_FixHIso)
    6610                 :             :         {
    6611   [ #  #  #  # ]:           0 :             ret |= ( Ct_FixHIso->lenCt > Ct_BaseIso->lenCt ) || memcmp( Ct_FixHIso->Ctbl, Ct_BaseIso->Ctbl, Ct_FixHIso->lenCt * sizeof( Ct_FixHIso->Ctbl[0] ) );
    6612   [ #  #  #  # ]:           0 :             ret |= ( Ct_FixHIso->lenNumH > Ct_BaseIso->lenNumH ) || memcmp( Ct_FixHIso->NumH, Ct_BaseIso->NumH, Ct_FixHIso->lenNumH * sizeof( Ct_BaseIso->NumH[0] ) );
    6613                 :             :         }
    6614                 :             :     }
    6615                 :             : 
    6616         [ -  + ]:         161 :     if (ret)
    6617                 :             :     {
    6618                 :           0 :         goto exit_error;
    6619                 :             :     }
    6620                 :             : 
    6621         [ +  + ]:         161 :     if (bReqTaut)
    6622                 :             :     {
    6623                 :             :         /* restore save "process isotopic" mark; temporarily set it to NO */
    6624                 :          14 :         t_group_info->bIgnoreIsotopic = bTautIgnoreIsotopic;
    6625                 :             :     }
    6626                 :             : 
    6627                 :             : 
    6628                 :             :     /* output the canonicalization results */
    6629                 :         161 :     pBCN->num_max = num_max;
    6630                 :         161 :     pBCN->num_at_tg = num_at_tg;
    6631                 :         161 :     pBCN->num_atoms = num_atoms;
    6632                 :             : 
    6633                 :         161 :     pBCN->ftcn[TAUT_NON].NeighList = NeighList[TAUT_NON]; NeighList[TAUT_NON] = NULL;
    6634                 :         161 :     pBCN->ftcn[TAUT_YES].NeighList = NeighList[TAUT_YES]; NeighList[TAUT_YES] = NULL;
    6635                 :             : 
    6636         [ +  + ]:         161 :     if (bReqTaut)
    6637                 :             :     {
    6638                 :             :         /* tautomeric results */
    6639                 :             : 
    6640                 :             :         /* base tautomeric structure, iBase = TAUT_YES */
    6641                 :             : 
    6642                 :          14 :         pBCN->ftcn[TAUT_YES].num_at_tg = num_at_tg;
    6643                 :          14 :         pBCN->ftcn[TAUT_YES].num_atoms = num_atoms;
    6644                 :             : 
    6645                 :          14 :         pBCN->ftcn[TAUT_YES].LinearCt = Ct_Base->Ctbl;            Ct_Base->Ctbl = NULL;
    6646                 :          14 :         pBCN->ftcn[TAUT_YES].nLenLinearCtAtOnly = s[iBase].nLenCTAtOnly;
    6647                 :          14 :         pBCN->ftcn[TAUT_YES].nMaxLenLinearCt = s[iBase].nLenCT + 1;
    6648                 :          14 :         pBCN->ftcn[TAUT_YES].nLenLinearCt = s[iBase].nLenCT;
    6649                 :             : 
    6650                 :          14 :         pBCN->ftcn[TAUT_YES].PartitionCt.Rank = nCanonRankBase;        nCanonRankBase = NULL;
    6651                 :          14 :         pBCN->ftcn[TAUT_YES].PartitionCt.AtNumber = nAtomNumberCanonBase;  nAtomNumberCanonBase = NULL;
    6652                 :          14 :         pBCN->ftcn[TAUT_YES].nSymmRankCt = nSymmRankBase;         nSymmRankBase = NULL;
    6653                 :             : 
    6654                 :          14 :         pBCN->ftcn[TAUT_YES].nNumHOrig = numH;                 numH = NULL;
    6655                 :          14 :         pBCN->ftcn[TAUT_YES].nNumH = Ct_Base->NumH;        Ct_Base->NumH = NULL;
    6656                 :          14 :         pBCN->ftcn[TAUT_YES].nLenNumH = inchi_min( maxlenNumH, Ct_Base->maxlenNumH );
    6657                 :             : 
    6658                 :             :         /* fixed H structure: exists only if the structure is tautomeric */
    6659                 :          14 :         pBCN->ftcn[TAUT_YES].nNumHOrigFixH = NULL;
    6660                 :          14 :         pBCN->ftcn[TAUT_YES].nNumHFixH = NULL;
    6661                 :          14 :         pBCN->ftcn[TAUT_YES].nLenNumHFixH = 0;
    6662                 :          14 :         pBCN->ftcn[TAUT_YES].nCanonFlags |= pCD[iBase].nCanonFlags;
    6663                 :             : 
    6664                 :          14 :         CleanNumH( pBCN->ftcn[TAUT_YES].nNumHOrig, pBCN->ftcn[TAUT_YES].nLenNumH );
    6665                 :          14 :         CleanNumH( pBCN->ftcn[TAUT_YES].nNumH, pBCN->ftcn[TAUT_YES].nLenNumH );
    6666                 :          14 :         CleanCt( pBCN->ftcn[TAUT_YES].LinearCt, pBCN->ftcn[TAUT_YES].nLenLinearCt );
    6667                 :             : 
    6668                 :             :         /* isotopic canonicalization */
    6669         [ -  + ]:          14 :         if (Ct_BaseIso)
    6670                 :             :         {
    6671                 :           0 :             pBCN->ftcn[TAUT_YES].PartitionCtIso.Rank = nCanonRankBaseIso;           nCanonRankBaseIso = NULL;
    6672                 :           0 :             pBCN->ftcn[TAUT_YES].PartitionCtIso.AtNumber = nAtomNumberCanonBaseIso;     nAtomNumberCanonBaseIso = NULL;
    6673                 :           0 :             pBCN->ftcn[TAUT_YES].nSymmRankCtIso = nSymmRankBaseIso;            nSymmRankBaseIso = NULL;
    6674                 :           0 :             pBCN->ftcn[TAUT_YES].iso_sort_keys = Ct_BaseIso->iso_sort_key;    Ct_BaseIso->iso_sort_key = NULL;
    6675                 :           0 :             pBCN->ftcn[TAUT_YES].iso_sort_keysOrig = iso_sort_keyBase;            iso_sort_keyBase = NULL;
    6676                 :           0 :             pBCN->ftcn[TAUT_YES].len_iso_sort_keys = len_iso_sort_keyBase;
    6677                 :           0 :             pBCN->ftcn[TAUT_YES].iso_exchg_atnos = Ct_BaseIso->iso_exchg_atnos; Ct_BaseIso->iso_exchg_atnos = NULL;
    6678                 :           0 :             pBCN->ftcn[TAUT_YES].iso_exchg_atnosOrig = iso_exchg_atnos;             iso_exchg_atnos = NULL;
    6679                 :             : 
    6680                 :           0 :             CleanIsoSortKeys( pBCN->ftcn[TAUT_YES].iso_sort_keys, pBCN->ftcn[TAUT_YES].len_iso_sort_keys );
    6681                 :           0 :             CleanIsoSortKeys( pBCN->ftcn[TAUT_YES].iso_sort_keysOrig, pBCN->ftcn[TAUT_YES].len_iso_sort_keys );
    6682                 :             :         }
    6683                 :             :     } /* tautomeric results */
    6684                 :             : 
    6685                 :             : 
    6686         [ +  + ]:         161 :     if (bReqNonTaut)
    6687                 :             :     {
    6688                 :             :         /* non-tautomeric results */
    6689                 :             : 
    6690                 :             :         /* TAUT_NON if tautomeric + non-tautomeric or special non-taut request
    6691                 :             :            TAUT_YES if the structure happened to be non-tautomeric while user requested tautomeric processing
    6692                 :             :            In both cases the correct index is iOther. TAUT_NON replaced with iOther 4-2-2004 */
    6693                 :             : 
    6694         [ +  - ]:         147 :         if (!bReqTaut)
    6695                 :             :         {
    6696                 :             :             /* rearrange the results for a non-tautomeric structure */
    6697                 :         147 :             nSymmRankFixH = nSymmRankNoTautH;           nSymmRankNoTautH = NULL;
    6698                 :         147 :             nCanonRankFixH = nCanonRankNoTautH;          nCanonRankNoTautH = NULL;
    6699                 :         147 :             nAtomNumberCanonFixH = nAtomNumberCanonNoTautH;    nAtomNumberCanonNoTautH = NULL;
    6700                 :         147 :             Ct_FixH = Ct_NoTautH;                 Ct_NoTautH = NULL;
    6701                 :             :             /* isotopic canonicalization */
    6702                 :         147 :             nSymmRankFixHIso = nSymmRankNoTautHIso;        nSymmRankNoTautHIso = NULL;
    6703                 :         147 :             nCanonRankFixHIso = nCanonRankNoTautHIso;       nCanonRankNoTautHIso = NULL;
    6704                 :         147 :             nAtomNumberCanonFixHIso = nAtomNumberCanonNoTautHIso; nAtomNumberCanonNoTautHIso = NULL;
    6705                 :         147 :             Ct_FixHIso = Ct_NoTautHIso;              Ct_NoTautHIso = NULL;
    6706                 :             : 
    6707   [ +  -  +  -  :         147 :             if (iOther == TAUT_YES && pBCN->ftcn[TAUT_NON].NeighList && !pBCN->ftcn[TAUT_YES].NeighList)
                   +  - ]
    6708                 :             :             {
    6709                 :             :                 /* here only non-taut results go to pBCN->ftcn[TAUT_YES]
    6710                 :             :                    Since non-taut NeighList is always in pBCN->ftcn[TAUT_NON].NeighList, move it to
    6711                 :             :                    pBCN->ftcn[TAUT_YES].NeighList. 2004-04-02.
    6712                 :             :                 */
    6713                 :         147 :                 pBCN->ftcn[TAUT_YES].NeighList = pBCN->ftcn[TAUT_NON].NeighList;
    6714                 :         147 :                 pBCN->ftcn[TAUT_NON].NeighList = NULL;
    6715                 :             :             }
    6716                 :             :         }
    6717                 :             : 
    6718                 :         147 :         pBCN->ftcn[iOther].num_at_tg = num_atoms;
    6719                 :         147 :         pBCN->ftcn[iOther].num_atoms = num_atoms;
    6720                 :             : 
    6721                 :         147 :         pBCN->ftcn[iOther].LinearCt = Ct_FixH->Ctbl;
    6722                 :         147 :         Ct_FixH->Ctbl = NULL;
    6723                 :         147 :         pBCN->ftcn[iOther].nLenLinearCtAtOnly = s[iOther].nLenCTAtOnly;
    6724                 :         147 :         pBCN->ftcn[iOther].nMaxLenLinearCt = s[iOther].nLenCTAtOnly + 1;
    6725                 :         147 :         pBCN->ftcn[iOther].nLenLinearCt = s[iOther].nLenCTAtOnly;
    6726                 :             : 
    6727                 :         147 :         pBCN->ftcn[iOther].PartitionCt.Rank = nCanonRankFixH;
    6728                 :         147 :         nCanonRankFixH = NULL;
    6729                 :         147 :         pBCN->ftcn[iOther].PartitionCt.AtNumber = nAtomNumberCanonFixH;
    6730                 :         147 :         nAtomNumberCanonFixH = NULL;
    6731                 :         147 :         pBCN->ftcn[iOther].nSymmRankCt = nSymmRankFixH;
    6732                 :         147 :         nSymmRankFixH = NULL;
    6733                 :             : 
    6734                 :         147 :         pBCN->ftcn[iOther].nNumHOrig = numHNoTautH;
    6735                 :         147 :         numHNoTautH = NULL;
    6736                 :         147 :         pBCN->ftcn[iOther].nNumH = Ct_FixH->NumH;
    6737                 :         147 :         Ct_FixH->NumH = NULL;
    6738                 :         147 :         pBCN->ftcn[iOther].nLenNumH = inchi_min( maxlenNumHNoTautH, Ct_FixH->maxlenNumH );
    6739                 :             : 
    6740                 :             :         /* fixed H structure: exists only if the structure is tautomeric */
    6741                 :         147 :         pBCN->ftcn[iOther].nNumHOrigFixH = NumHfixed;
    6742                 :         147 :         NumHfixed = NULL;
    6743                 :         147 :         pBCN->ftcn[iOther].nNumHFixH = Ct_FixH->NumHfixed;
    6744                 :         147 :         Ct_FixH->NumHfixed = NULL;
    6745                 :         147 :         pBCN->ftcn[iOther].nLenNumHFixH = num_atoms;
    6746                 :         147 :         pBCN->ftcn[iOther].nCanonFlags |= pCD[iOther].nCanonFlags;
    6747                 :             : 
    6748                 :             :         /* original H */
    6749                 :         147 :         CleanNumH( pBCN->ftcn[iOther].nNumHOrig, pBCN->ftcn[iOther].nLenNumH );
    6750                 :         147 :         CleanNumH( pBCN->ftcn[iOther].nNumHOrigFixH, pBCN->ftcn[iOther].nLenNumH );
    6751                 :             :         /* canonical H positions */
    6752                 :         147 :         CleanNumH( pBCN->ftcn[iOther].nNumH, pBCN->ftcn[iOther].nLenNumH );
    6753                 :         147 :         CleanNumH( pBCN->ftcn[iOther].nNumHFixH, pBCN->ftcn[iOther].nLenNumH );
    6754                 :             : 
    6755                 :             :         /* connection table */
    6756                 :         147 :         CleanCt( pBCN->ftcn[iOther].LinearCt, pBCN->ftcn[iOther].nLenLinearCt );
    6757                 :             : 
    6758                 :             :        /* isotopic canonicalization */
    6759         [ -  + ]:         147 :         if (Ct_FixHIso)
    6760                 :             :         {
    6761                 :           0 :             pBCN->ftcn[iOther].PartitionCtIso.Rank = nCanonRankFixHIso;        nCanonRankFixHIso = NULL;
    6762                 :           0 :             pBCN->ftcn[iOther].PartitionCtIso.AtNumber = nAtomNumberCanonFixHIso;  nAtomNumberCanonFixHIso = NULL;
    6763                 :           0 :             pBCN->ftcn[iOther].nSymmRankCtIso = nSymmRankFixHIso;         nSymmRankFixHIso = NULL;
    6764                 :           0 :             pBCN->ftcn[iOther].iso_sort_keys = Ct_FixHIso->iso_sort_key; Ct_FixHIso->iso_sort_key = NULL;
    6765                 :           0 :             pBCN->ftcn[iOther].iso_sort_keysOrig = iso_sort_key_NoTautH;     iso_sort_key_NoTautH = NULL;
    6766                 :           0 :             pBCN->ftcn[iOther].len_iso_sort_keys = len_iso_sort_key_NoTautH;
    6767                 :             : 
    6768                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6769                 :             :             MergeCleanIsoSortKeys( pBCN->ftcn[iOther].iso_sort_keys, Ct_FixHIso->iso_sort_key_Hfixed, pBCN->ftcn[iOther].len_iso_sort_keys );
    6770                 :             :             MergeCleanIsoSortKeys( pBCN->ftcn[iOther].iso_sort_keysOrig, iso_sort_key_Hfixed, pBCN->ftcn[iOther].len_iso_sort_keys );
    6771                 :             : #else
    6772                 :           0 :             CleanIsoSortKeys( pBCN->ftcn[iOther].iso_sort_keys, pBCN->ftcn[iOther].len_iso_sort_keys );
    6773                 :           0 :             CleanIsoSortKeys( pBCN->ftcn[iOther].iso_sort_keysOrig, pBCN->ftcn[iOther].len_iso_sort_keys );
    6774                 :             : #endif
    6775                 :             :         }
    6776                 :             :     }  /* non-tautomeric results */
    6777                 :             : 
    6778                 :         161 :     goto exit_function;
    6779                 :             : 
    6780                 :             : 
    6781                 :           0 : exit_error_alloc:
    6782                 :           0 :     ret = CT_OUT_OF_RAM;
    6783                 :           0 :     goto exit_function;
    6784                 :             : 
    6785                 :           0 : exit_error:
    6786   [ #  #  #  # ]:           0 :     if (!RETURNED_ERROR( ret ))
    6787                 :             :     {
    6788                 :           0 :         ret = CT_CANON_ERR;
    6789                 :             :     }
    6790                 :           0 :     goto exit_function;
    6791                 :             : 
    6792                 :             : 
    6793                 :         161 : exit_function:
    6794                 :             : 
    6795                 :             : #define FREE_CONTABLE( X) if (X) {CTableFree( X);inchi_free( X);}
    6796                 :             : #define FREE_ARRAY( X) if (X) inchi_free( X);
    6797                 :             : 
    6798                 :         161 :     FreeNeighList( NeighList[TAUT_NON] );
    6799                 :         161 :     FreeNeighList( NeighList[TAUT_YES] );
    6800                 :             : 
    6801   [ +  -  +  - ]:         161 :     FREE_CONTABLE( Ct_NoH )
    6802   [ +  +  +  - ]:         161 :         FREE_CONTABLE( Ct_NoTautH )
    6803   [ +  +  +  - ]:         161 :         FREE_CONTABLE( Ct_Base )
    6804   [ +  +  +  - ]:         161 :         FREE_CONTABLE( Ct_FixH )
    6805   [ -  +  -  - ]:         161 :         FREE_CONTABLE( Ct_Temp )
    6806                 :             :         /* isotopic canonicalization */
    6807   [ -  +  -  - ]:         161 :         FREE_CONTABLE( Ct_NoTautHIso )
    6808   [ -  +  -  - ]:         161 :         FREE_CONTABLE( Ct_BaseIso )
    6809   [ -  +  -  - ]:         161 :         FREE_CONTABLE( Ct_FixHIso )
    6810                 :             : 
    6811                 :             :         /* free the first two pointers from pBCN->pRankStack */
    6812   [ +  -  +  - ]:         161 :         FREE_ARRAY( nRank )
    6813   [ +  -  +  - ]:         161 :         FREE_ARRAY( nAtomNumber )
    6814                 :             : 
    6815         [ +  - ]:         161 :         if (pBCN->pRankStack)
    6816                 :             :         {
    6817                 :         161 :             pBCN->pRankStack[0] =
    6818                 :         161 :                 pBCN->pRankStack[1] = NULL;
    6819                 :             :         }
    6820                 :             : 
    6821                 :             : #if ( USE_AUX_RANKING == 1 )
    6822   [ +  -  +  - ]:         161 :     FREE_ARRAY( nRankAux )
    6823   [ +  -  +  - ]:         161 :         FREE_ARRAY( nAtomNumberAux )
    6824   [ +  -  +  - ]:         161 :         FREE_ARRAY( pAtomInvariantAux )
    6825                 :             : #endif
    6826                 :             : 
    6827   [ +  -  +  - ]:         161 :         FREE_ARRAY( pAtomInvariant )
    6828                 :             : 
    6829   [ +  -  +  - ]:         161 :         FREE_ARRAY( nCanonRankNoH )
    6830   [ +  -  +  - ]:         161 :         FREE_ARRAY( nAtomNumberCanonNoH )
    6831   [ +  -  +  - ]:         161 :         FREE_ARRAY( nSymmRankNoH )
    6832                 :             : 
    6833   [ +  +  +  - ]:         161 :         FREE_ARRAY( nSymmRankNoTautH )
    6834   [ +  +  +  - ]:         161 :         FREE_ARRAY( nCanonRankNoTautH )
    6835   [ +  +  +  - ]:         161 :         FREE_ARRAY( nAtomNumberCanonNoTautH )
    6836   [ +  +  +  - ]:         161 :         FREE_ARRAY( numHNoTautH )
    6837                 :             : 
    6838   [ -  +  -  - ]:         161 :         FREE_ARRAY( nSymmRankBase )
    6839   [ -  +  -  - ]:         161 :         FREE_ARRAY( nCanonRankBase )
    6840   [ -  +  -  - ]:         161 :         FREE_ARRAY( nAtomNumberCanonBase )
    6841   [ -  +  -  - ]:         161 :         FREE_ARRAY( numH )
    6842                 :             : 
    6843   [ -  +  -  - ]:         161 :         FREE_ARRAY( nSymmRankFixH )
    6844   [ -  +  -  - ]:         161 :         FREE_ARRAY( nCanonRankFixH )
    6845   [ -  +  -  - ]:         161 :         FREE_ARRAY( nAtomNumberCanonFixH )
    6846   [ -  +  -  - ]:         161 :         FREE_ARRAY( NumHfixed )
    6847                 :             : 
    6848                 :             :         /* isotopic canonicalization */
    6849                 :             : 
    6850   [ -  +  -  - ]:         161 :         FREE_ARRAY( nSymmRankNoTautHIso )
    6851   [ -  +  -  - ]:         161 :         FREE_ARRAY( nCanonRankNoTautHIso )
    6852   [ -  +  -  - ]:         161 :         FREE_ARRAY( nAtomNumberCanonNoTautHIso )
    6853   [ -  +  -  - ]:         161 :         FREE_ARRAY( iso_sort_key_NoTautH )
    6854                 :             : 
    6855   [ -  +  -  - ]:         161 :         FREE_ARRAY( nSymmRankBaseIso )
    6856   [ -  +  -  - ]:         161 :         FREE_ARRAY( nCanonRankBaseIso )
    6857   [ -  +  -  - ]:         161 :         FREE_ARRAY( nAtomNumberCanonBaseIso )
    6858   [ -  +  -  - ]:         161 :         FREE_ARRAY( iso_sort_keyBase )
    6859   [ -  +  -  - ]:         161 :         FREE_ARRAY( iso_exchg_atnos )
    6860                 :             : 
    6861   [ -  +  -  - ]:         161 :         FREE_ARRAY( nSymmRankFixHIso )
    6862   [ -  +  -  - ]:         161 :         FREE_ARRAY( nCanonRankFixHIso )
    6863   [ -  +  -  - ]:         161 :         FREE_ARRAY( nAtomNumberCanonFixHIso )
    6864                 :             : 
    6865                 :             : #if ( USE_ISO_SORT_KEY_HFIXED == 1 )
    6866                 :             :         FREE_ARRAY( iso_sort_key_Hfixed )
    6867                 :             : #endif
    6868                 :             : 
    6869   [ +  -  +  - ]:         161 :         FREE_ARRAY( nTempRank )
    6870                 :             : 
    6871                 :             : #undef FREE_CONTABLE
    6872                 :             : #undef FREE_ARRAY
    6873                 :             : 
    6874                 :         161 :         return ret;
    6875                 :             : }
        

Generated by: LCOV version 2.0-1