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