LCOV - code coverage report
Current view: top level - src - ichican2.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 57.5 % 2127 1224
Test Date: 2026-05-04 07:05:02 Functions: 79.3 % 58 46
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 35.9 % 1834 658

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

Generated by: LCOV version 2.0-1