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