Branch data Line data Source code
1 : : /*
2 : : * SPDX-License-Identifier: MIT
3 : : * Copyright (c) 2024 IUPAC and InChI Trust
4 : : */
5 : :
6 : : #include <string.h>
7 : :
8 : : #include "mode.h"
9 : : #include "ichimain.h"
10 : : #include "ichimake.h"
11 : : #include "ichi_io.h"
12 : :
13 : : #include "bcf_s.h"
14 : :
15 : : /*
16 : :
17 : : Generate substrings of whole-structure InChI/AuxInfo
18 : :
19 : : */
20 : :
21 : :
22 : : /****************************************************************************
23 : : Produce Hill formula substring of the whole structure InChI string
24 : : ****************************************************************************/
25 : 122 : int str_HillFormula( INCHI_SORT *pINChISort,
26 : : INCHI_IOS_STRING *strbuf,
27 : : int *bOverflow,
28 : : int bOutType,
29 : : int num_components,
30 : : int bUseMulipliers )
31 : : {
32 : : int i, ii, nUsedLength0;
33 : : INCHI_SORT *is, *is0;
34 : : INChI *pINChI, *pINChI_Prev;
35 : : int mult, eq2prev, bNext;
36 : :
37 : 122 : nUsedLength0 = strbuf->nUsedLength;
38 : :
39 [ - + ]: 122 : if (!( is0 = pINChISort ))
40 : : {
41 : 0 : return nUsedLength0;
42 : : }
43 : 122 : i = 0;
44 [ - + - - : 122 : pINChI_Prev = ( 0 <= ( ii = GET_II( bOutType, is0 ) ) ) ? is0->pINChI[ii] : NULL;
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
45 : 122 : mult = 0;
46 : 122 : bNext = 0;
47 : :
48 : : /* For each connected component */
49 [ + + ]: 283 : for (i++; i <= num_components; i++)
50 : : {
51 : :
52 : 200 : pINChI = ( i < num_components &&
53 [ - + - - : 39 : ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) )
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
54 : : ? is->pINChI[ii]
55 [ + + ]: 200 : : NULL;
56 : :
57 [ + + ]: 161 : eq2prev = bUseMulipliers &&
58 [ + - ]: 39 : pINChI &&
59 : 39 : pINChI_Prev &&
60 [ + - ]: 39 : pINChI->szHillFormula &&
61 [ + - ]: 39 : pINChI_Prev->szHillFormula &&
62 [ + - + - ]: 361 : pINChI->szHillFormula[0] &&
63 [ + + ]: 39 : !strcmp( pINChI_Prev->szHillFormula, pINChI->szHillFormula );
64 : :
65 [ + + ]: 161 : if (eq2prev)
66 : : {
67 : 15 : mult++; /* mult = (number of non-empty equal items)-1 */
68 : 15 : continue;
69 : : }
70 : : else
71 : : {
72 : : int ok;
73 [ + + ]: 146 : if (bNext++)
74 : : {
75 : 24 : MakeDelim( ".", strbuf, bOverflow );
76 : : }
77 : :
78 : 292 : ok = pINChI_Prev &&
79 [ + - + - ]: 292 : pINChI_Prev->szHillFormula &&
80 [ + - ]: 146 : pINChI_Prev->szHillFormula[0];
81 : :
82 [ + - ]: 146 : if (ok)
83 : : {
84 : 146 : MakeMult( mult + 1, "", strbuf, 0, bOverflow );
85 : 146 : MakeHillFormulaString( pINChI_Prev->szHillFormula,
86 : : strbuf,
87 : : bOverflow );
88 : : }
89 : : }
90 : 146 : pINChI_Prev = pINChI;
91 : 146 : mult = 0; /* we do not know whether the item is empty */
92 : : }
93 : :
94 : 122 : return ( strbuf->nUsedLength - nUsedLength0 );
95 : : }
96 : :
97 : :
98 : : /****************************************************************************
99 : : Produce Hill formula substring of the whole structure InChI string:
100 : : 2nd appearance (FixedH).
101 : : ****************************************************************************/
102 : 0 : int str_HillFormula2( INCHI_SORT *pINChISort, /* non-taut */
103 : : INCHI_SORT *pINChISort2, /* taut */
104 : : INCHI_IOS_STRING *strbuf,
105 : : int *bOverflow,
106 : : int bOutType,
107 : : int num_components,
108 : : int bUseMulipliers )
109 : : {
110 : : int i, ii, ii2, nUsedLength0;
111 : : INCHI_SORT *is, *is2, *is0, *is20;
112 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
113 : : int mult, eq2prev, bNext, bEqToTaut;
114 : :
115 : 0 : is = NULL;
116 : 0 : is2 = NULL;
117 : 0 : is0 = pINChISort;
118 : 0 : is20 = pINChISort2;
119 : 0 : i = 0;
120 : 0 : nUsedLength0 = strbuf->nUsedLength;
121 : :
122 [ # # # # : 0 : pINChI_Prev = ( 0 <= ( ii = GET_II( bOutType, is0 ) ) ) ? is0->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
123 [ # # # # : 0 : pINChI_Taut_Prev = ( 0 <= ( ii2 = GET_II( OUT_T1, is20 ) ) ) ? is20->pINChI[ii2] : NULL;
# # # # #
# ]
124 : 0 : mult = 0;
125 : 0 : bNext = 0;
126 : 0 : bEqToTaut = 1;
127 [ # # ]: 0 : bEqToTaut = bEqToTaut &&
128 [ # # ]: 0 : pINChI_Prev &&
129 : 0 : pINChI_Taut_Prev &&
130 [ # # ]: 0 : !pINChI_Taut_Prev->bDeleted &&
131 [ # # ]: 0 : pINChI_Prev->szHillFormula &&
132 [ # # # # ]: 0 : pINChI_Taut_Prev->szHillFormula &&
133 [ # # ]: 0 : !strcmp( pINChI_Prev->szHillFormula, pINChI_Taut_Prev->szHillFormula );
134 : :
135 : : /* For each connected component */
136 [ # # ]: 0 : for (i++; i <= num_components; i++)
137 : : {
138 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
139 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
140 [ # # # # : 0 : if (bEqToTaut && ( pINChI || pINChI_Taut ))
# # ]
141 : : {
142 [ # # # # ]: 0 : bEqToTaut = pINChI && pINChI_Taut && !pINChI_Taut->bDeleted &&
143 [ # # # # : 0 : pINChI->szHillFormula && pINChI_Taut->szHillFormula &&
# # ]
144 [ # # ]: 0 : !strcmp( pINChI->szHillFormula, pINChI_Taut->szHillFormula );
145 : : }
146 : :
147 [ # # ]: 0 : eq2prev = bUseMulipliers &&
148 [ # # ]: 0 : pINChI && pINChI_Prev &&
149 [ # # ]: 0 : pINChI->szHillFormula &&
150 [ # # ]: 0 : pINChI_Prev->szHillFormula &&
151 [ # # # # ]: 0 : pINChI->szHillFormula[0] &&
152 [ # # ]: 0 : !strcmp( pINChI_Prev->szHillFormula, pINChI->szHillFormula );
153 : :
154 [ # # ]: 0 : if (eq2prev)
155 : : {
156 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
157 : 0 : continue;
158 : : }
159 : : else
160 : : {
161 [ # # ]: 0 : if (bNext++)
162 : : {
163 : 0 : MakeDelim( ".", strbuf, bOverflow );
164 : : }
165 [ # # # # : 0 : if (pINChI_Prev && pINChI_Prev->szHillFormula && pINChI_Prev->szHillFormula[0])
# # ]
166 : : {
167 : 0 : MakeMult( mult + 1, "", strbuf, 0, bOverflow );
168 : 0 : MakeHillFormulaString( pINChI_Prev->szHillFormula, strbuf, bOverflow );
169 : : }
170 : : }
171 : 0 : pINChI_Prev = pINChI;
172 : 0 : mult = 0; /* we do not know whether the item is empty */
173 : : }
174 : :
175 [ # # ]: 0 : if (bEqToTaut)
176 : 0 : strbuf->nUsedLength = nUsedLength0;
177 : :
178 : : {
179 : 0 : strbuf->pStr[strbuf->nUsedLength] = '\0';
180 : : }
181 : :
182 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
183 : : }
184 : :
185 : :
186 : : /****************************************************************************
187 : : Produce connections substring of InChI string for the whole structure
188 : : ****************************************************************************/
189 : 122 : int str_Connections( CANON_GLOBALS *pCG,
190 : : INCHI_SORT *pINChISort,
191 : : INCHI_IOS_STRING *strbuf,
192 : : int *bOverflow,
193 : : int bOutType,
194 : : int ATOM_MODE,
195 : : int num_components,
196 : : int bUseMulipliers )
197 : : {
198 : : int i, ii, nUsedLength0;
199 : : INCHI_SORT *is, *is0;
200 : : INChI *pINChI, *pINChI_Prev;
201 : : int mult, eq2prev, bNext, nNumEmpty;
202 : :
203 : 122 : nUsedLength0 = strbuf->nUsedLength;
204 [ - + ]: 122 : if (!( is0 = pINChISort ))
205 : : {
206 : 0 : return nUsedLength0;
207 : : }
208 : 122 : i = 0;
209 [ - + - - : 122 : pINChI_Prev = ( 0 <= ( ii = GET_II( bOutType, is0 ) ) ) ? is0->pINChI[ii] : NULL;
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
210 : 122 : is = NULL;
211 : 122 : mult = 0;
212 : 122 : bNext = 0;
213 : 122 : nNumEmpty = 0;
214 : :
215 : : /* For each connected component... */
216 [ + + ]: 283 : for (i++; i <= num_components; i++)
217 : : {
218 [ + + - + : 161 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
219 [ + + ]: 161 : eq2prev = bUseMulipliers &&
220 [ + - + + ]: 39 : pINChI && pINChI_Prev && pINChI->lenConnTable > 1 &&
221 [ + - + + ]: 329 : pINChI_Prev->lenConnTable == pINChI->lenConnTable &&
222 : 7 : !memcmp( pINChI_Prev->nConnTable, pINChI->nConnTable,
223 [ + - ]: 7 : pINChI_Prev->lenConnTable * sizeof( pINChI->nConnTable[0] ) );
224 [ + + ]: 161 : if (eq2prev)
225 : : {
226 : 7 : mult++; /* mult = (number of non-empty equal items)-1 */
227 : 7 : continue;
228 : : }
229 : : else
230 : : {
231 [ + - ]: 154 : if (pINChI_Prev)
232 : : {
233 [ + + ]: 154 : if (bNext++)
234 : : {
235 : 32 : MakeDelim( sCompDelim, strbuf, bOverflow );
236 : : }
237 [ + - + + ]: 154 : if (pINChI_Prev && pINChI_Prev->lenConnTable > 1)
238 : : {
239 : 70 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
240 : 70 : MakeCtStringNew( pCG, pINChI_Prev->nConnTable,
241 : : pINChI_Prev->lenConnTable,
242 : : 0, NULL,
243 : : pINChI_Prev->nNumberOfAtoms,
244 : : strbuf, ATOM_MODE, bOverflow );
245 : : }
246 : : else
247 : : {
248 : 84 : nNumEmpty++;
249 : : }
250 : : }
251 : : }
252 : 154 : pINChI_Prev = pINChI;
253 : 154 : mult = 0; /* we do not know whether the item is empty */
254 : : }
255 [ + + + + ]: 122 : if (nNumEmpty == num_components && strbuf->nUsedLength > nUsedLength0)
256 : : {
257 : 10 : strbuf->nUsedLength = nUsedLength0;
258 : 10 : strbuf->pStr[strbuf->nUsedLength] = '\0';
259 : : }
260 : : /*
261 : : if ( nNumEmpty == num_components && tot_len > tot_len_inp ) {
262 : : tot_len = tot_len_inp;
263 : : strbuf->pStr[tot_len] = '\0';
264 : : }
265 : : */
266 : :
267 : 122 : return ( strbuf->nUsedLength - nUsedLength0 );
268 : : }
269 : :
270 : :
271 : : /****************************************************************************
272 : : Produce H[ydrogens] substring of the whole structure InChI string
273 : : ****************************************************************************/
274 : 84 : int str_H_atoms( INCHI_SORT *pINChISort,
275 : : INCHI_IOS_STRING *strbuf,
276 : : int *bOverflow,
277 : : int bOutType,
278 : : int ATOM_MODE,
279 : : int TAUT_MODE,
280 : : int num_components,
281 : : int bUseMulipliers )
282 : : {
283 : : int i, j, ii, len_H, nUsedLength0;
284 : : INCHI_SORT *is, *is0;
285 : : INChI *pINChI, *pINChI_Prev;
286 : : int mult, eq2prev, bNext, bNotEmpty, nNumEmpty;
287 : :
288 : 84 : nNumEmpty = 0;
289 : 84 : is0 = pINChISort;
290 : 84 : is = NULL;
291 : 84 : i = 0;
292 [ - + - - : 84 : pINChI_Prev = ( 0 <= ( ii = GET_II( bOutType, is0 ) ) ) ? is0->pINChI[ii] : NULL;
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
293 : 84 : mult = 0;
294 : 84 : bNext = 0;
295 : 84 : nUsedLength0 = strbuf->nUsedLength;
296 : :
297 : : /* For each connected component... */
298 [ + + ]: 200 : for (i++; i <= num_components; i++)
299 : : {
300 : :
301 [ + + - + : 116 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
302 : : /*========== compare to previous ============*/
303 [ + + ]: 116 : eq2prev = bUseMulipliers &&
304 [ + - - + : 32 : pINChI && pINChI_Prev && ( pINChI->nNumberOfAtoms > 0 || pINChI->lenTautomer > 1 ) &&
- - ]
305 [ + + ]: 32 : pINChI_Prev->nNumberOfAtoms == pINChI->nNumberOfAtoms &&
306 [ + - ]: 18 : ( !pINChI_Prev->nNumberOfAtoms || !memcmp( pINChI_Prev->nNum_H, pINChI->nNum_H,
307 [ + - + + : 244 : pINChI_Prev->nNumberOfAtoms * sizeof( pINChI->nNum_H[0] ) ) ) &&
+ - ]
308 : 12 : !CompareTautNonIsoPartOfINChI( pINChI_Prev, pINChI );
309 : :
310 [ + + + + ]: 116 : if (eq2prev && pINChI_Prev->lenTautomer <= 1)
311 : : {
312 : : /* make sure it is not empty */
313 : 11 : eq2prev = 0;
314 [ + + ]: 14 : for (j = 0; j < pINChI_Prev->nNumberOfAtoms; j++)
315 : : {
316 [ + + ]: 11 : if (pINChI_Prev->nNum_H[j])
317 : : {
318 : 8 : eq2prev = 1;
319 : 8 : break;
320 : : }
321 : : }
322 : : }
323 [ + + ]: 116 : if (eq2prev)
324 : : {
325 : 9 : mult++; /* mult = (number of non-empty equal items)-1 */
326 : 9 : continue;
327 : : }
328 : : else
329 : : {
330 [ + - ]: 107 : if (pINChI_Prev)
331 : : {
332 : : /* delimiter */
333 [ + + ]: 107 : if (bNext++)
334 : : {
335 : 23 : MakeDelim( sCompDelim, strbuf, bOverflow );
336 : : }
337 : : /* verify non-empty */
338 : 107 : bNotEmpty = 0;
339 [ + - ]: 107 : if (pINChI_Prev)
340 : : {
341 : 107 : bNotEmpty = ( pINChI_Prev->lenTautomer > 1 );
342 [ + + ]: 107 : if (!bNotEmpty)
343 : : {
344 [ + + ]: 119 : for (j = 0; j < pINChI_Prev->nNumberOfAtoms; j++)
345 : : {
346 [ + + ]: 101 : if (pINChI_Prev->nNum_H[j])
347 : : {
348 : 83 : bNotEmpty = 1;
349 : 83 : break;
350 : : }
351 : : }
352 : : }
353 : : }
354 [ + + ]: 107 : if (bNotEmpty)
355 : : {
356 : 89 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
357 : : /* H-atoms */
358 : 89 : len_H = MakeHString( 0, pINChI_Prev->nNum_H, pINChI_Prev->nNumberOfAtoms,
359 : : strbuf, ATOM_MODE, bOverflow );
360 : : /* tautomeric groups */
361 : 89 : MakeTautString( pINChI_Prev->nTautomer, pINChI_Prev->lenTautomer, ( 0 != len_H ),
362 : : strbuf, TAUT_MODE, bOverflow );
363 : : }
364 : : else
365 : : {
366 : 18 : nNumEmpty++;
367 : : }
368 : : }
369 : : }
370 : 107 : pINChI_Prev = pINChI;
371 : 107 : mult = 0; /* we do not know whether the item is empty */
372 : : }
373 [ - + - - ]: 84 : if (nNumEmpty == num_components && strbuf->nUsedLength > nUsedLength0)
374 : : {
375 : 0 : strbuf->nUsedLength = nUsedLength0;
376 : 0 : strbuf->pStr[nUsedLength0] = '\0';
377 : : }
378 : : /*
379 : : if ( nNumEmpty == num_components && tot_len > tot_len_inp ) {
380 : : tot_len = tot_len_inp;
381 : : strbuf->pStr[tot_len] = '\0';
382 : : }
383 : : */
384 : :
385 : 84 : return ( strbuf->nUsedLength - nUsedLength0 );
386 : : }
387 : :
388 : :
389 : : /****************************************************************************
390 : : Produce charge substring of the whole structure InChI string
391 : : ****************************************************************************/
392 : 19 : int str_Charge2( INCHI_SORT *pINChISort,
393 : : INCHI_SORT *pINChISort2,
394 : : INCHI_IOS_STRING *strbuf,
395 : : int *bOverflow,
396 : : int bOutType,
397 : : int num_components,
398 : : int bSecondNonTautPass,
399 : : int bOmitRepetitions,
400 : : int bUseMulipliers )
401 : : {
402 : : int i, ii, ii2, nUsedLength0;
403 : : INCHI_SORT *is, *is2, *is0, *is20;
404 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
405 : : int nTotalCharge, nTotalCharge_Prev, nTotalCharge_Taut; /* djb-rwth: removing redundant variables */
406 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
407 : : const char *pPrevEquStr, *pCurrEquStr;
408 : : int multPrevEquStr;
409 : 19 : pINChI_Taut = NULL;
410 : 19 : pINChI_Prev = NULL;
411 : 19 : pINChI_Taut_Prev = NULL;
412 : 19 : mult = 0;
413 : 19 : bNext = 0;
414 : 19 : is = NULL;
415 : 19 : is2 = NULL;
416 : 19 : is0 = pINChISort;
417 [ - + ]: 19 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
418 : : /* djb-rwth: removing redundant code */
419 : 19 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
420 : 19 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
421 : 19 : multPrevEquStr = 0;
422 : 19 : nUsedLength0 = strbuf->nUsedLength;
423 : :
424 : : /* For each connected component... */
425 [ + + ]: 83 : for (i = 0; i <= num_components; i++)
426 : : {
427 : :
428 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
429 [ + + - + : 64 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
430 : : /*================ compare sp3 to previous =====================*/
431 [ - + ]: 64 : if (bSecondNonTautPass)
432 : : {
433 : : /* component that was output on the 1st pass */
434 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
435 : : }
436 : : /*========= if bSecondNonTautPass then compare non-iso non-taut stereo to non-iso taut ========*/
437 : 64 : eq2taut = 0;
438 [ + - - + : 64 : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions)
- - ]
439 : : {
440 [ # # # # ]: 0 : eq2taut = pINChI && pINChI_Taut && !pINChI_Taut->bDeleted &&
441 [ # # # # : 0 : ( nTotalCharge = pINChI->nTotalCharge ) && ( nTotalCharge_Taut = pINChI_Taut->nTotalCharge ) &&
# # # # ]
442 : : nTotalCharge == nTotalCharge_Taut;
443 [ # # ]: 0 : eq2taut = eq2taut ? ( iiEQU | iitNONTAUT ) : 0;
444 : : }
445 [ - + ]: 64 : if (eq2taut)
446 : : {
447 : : /* we may be here only in case of the second (non-taut) pass */
448 : : /* current non-taut stereo has been found to be same as tautomeric */
449 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
450 : : {
451 : : /* previous component exists; output it */
452 [ # # ]: 0 : if (bNext++)
453 : : {
454 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
455 : : }
456 [ # # ]: 0 : if ((nTotalCharge_Prev = pINChI_Prev->nTotalCharge)) /* djb-rwth: addressing LLVM warning */
457 : : {
458 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
459 : 0 : inchi_strbuf_printf( strbuf, "%+d", nTotalCharge_Prev );
460 : : }
461 : : }
462 : : else
463 : : {
464 [ # # # # : 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms && !pINChI_Taut_Prev->bDeleted)
# # ]
465 : : {
466 : : /* previous non-taut component exists only in taut list */
467 [ # # ]: 0 : if (bNext++)
468 : : {
469 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
470 : : }
471 : : }
472 : : }
473 : : /* we have found pINChI->nTotalCharge same as in pINChI_Taut */
474 : : /* output this (current) equivalence as '*', that is, same as tautomeric */
475 : : /* that was printed on the 1st pass. */
476 : :
477 : 0 : pCurrEquStr = EquString( eq2taut );
478 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
479 : : {
480 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
481 : : {
482 : 0 : multPrevEquStr++;
483 : : }
484 : : else
485 : : {
486 : : /* new EqStr is different; output it */
487 [ # # ]: 0 : if (bNext++)
488 : : {
489 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
490 : : }
491 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
492 : 0 : pPrevEquStr = pCurrEquStr;
493 : 0 : multPrevEquStr = 1;
494 : : }
495 : : }
496 : : else
497 : : {
498 : 0 : pPrevEquStr = pCurrEquStr;
499 : 0 : multPrevEquStr = 1;
500 : : }
501 : :
502 : 0 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
503 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
504 : 0 : mult = 0;
505 : 0 : eq2tautPrev = 1; /* pINChI_Prev sp2 does not exist */
506 : : }
507 : : else
508 : : {
509 [ + + ]: 64 : if (eq2tautPrev)
510 : : {
511 : : /* at this point pINChI_Prev does not exist; however, pINChI */
512 : : /*might have been discovered and it is different from pINChI_Taut */
513 [ - + - - ]: 19 : if (multPrevEquStr && pPrevEquStr)
514 : : {
515 : : /* new EqStr is different; output it */
516 [ # # ]: 0 : if (bNext++)
517 : : {
518 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
519 : : }
520 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
521 : 0 : pPrevEquStr = NULL;
522 : 0 : multPrevEquStr = 0;
523 : : }
524 : 19 : eq2tautPrev = 0;
525 : 19 : pINChI_Prev = pINChI;
526 : 19 : pINChI_Taut_Prev = pINChI_Taut;
527 : 19 : mult = 0;
528 : : }
529 : : else
530 : : {
531 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp3 */
532 : : /*================ compare sp3 to previous =====================*/
533 [ + + ]: 45 : eq2prev = bUseMulipliers &&
534 [ + - ]: 26 : pINChI && pINChI_Prev &&
535 [ + - + + : 90 : ( nTotalCharge = pINChI->nTotalCharge ) && ( nTotalCharge_Prev = pINChI_Prev->nTotalCharge ) &&
+ + + + ]
536 : : nTotalCharge == nTotalCharge_Prev;
537 [ + + ]: 45 : if (eq2prev)
538 : : {
539 : 5 : mult++; /* mult = (number of non-empty equal items)-1 */
540 : 5 : continue;
541 : : }
542 : : else
543 : : {
544 [ + + ]: 40 : if (bNext++)
545 : : {
546 : 21 : MakeDelim( sCompDelim, strbuf, bOverflow );
547 : : }
548 [ + - + - ]: 40 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
549 : : {
550 [ + + ]: 40 : if ((nTotalCharge_Prev = pINChI_Prev->nTotalCharge)) /* djb-rwth: addressing LLVM warning */
551 : : {
552 : : /* pINChI_Prev exists and has charge info */
553 : 25 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
554 : 25 : inchi_strbuf_printf( strbuf, "%+d", nTotalCharge_Prev );
555 : : }
556 : : /* else charge is not present in pINChI_Prev */
557 : : }
558 : : else
559 : : {
560 : : /* djb-rwth: removing redundant code */
561 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
562 : : if (!(bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms && !pINChI_Taut_Prev->bDeleted))
563 : : {
564 : : int stop = 1; /* <BRKPT> */
565 : : }
566 : : #endif
567 : : }
568 : : }
569 : 40 : pINChI_Prev = pINChI;
570 : 40 : pINChI_Taut_Prev = pINChI_Taut;
571 : 40 : mult = 0; /* we do not know whether the item is empty */
572 : : }
573 : : }
574 : : }
575 : :
576 : 19 : return ( strbuf->nUsedLength - nUsedLength0 );
577 : : }
578 : :
579 : :
580 : : /****************************************************************************
581 : : Produce FixedH substring of the whole structure InChI string
582 : : ****************************************************************************/
583 : 0 : int str_FixedH_atoms( INCHI_SORT *pINChISort,
584 : : INCHI_IOS_STRING *strbuf,
585 : : int *bOverflow,
586 : : int bOutType,
587 : : int ATOM_MODE,
588 : : int num_components,
589 : : int bUseMulipliers )
590 : : {
591 : : int i, j, ii, nNumEmpty, nUsedLength0;
592 : : INCHI_SORT *is, *is0;
593 : : INChI *pINChI, *pINChI_Prev;
594 : : int mult, eq2prev, bNext, bNotEmpty;
595 : :
596 : 0 : is = NULL;
597 : 0 : is0 = pINChISort;
598 : 0 : i = 0;
599 [ # # # # : 0 : pINChI_Prev = ( 0 <= ( ii = GET_II( bOutType, is0 ) ) ) ? is0->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
600 : 0 : mult = 0;
601 : 0 : bNext = 0;
602 : 0 : nNumEmpty = 0;
603 : 0 : nUsedLength0 = strbuf->nUsedLength;
604 : :
605 : : /* For each connected component... */
606 [ # # ]: 0 : for (i++; i <= num_components; i++)
607 : : {
608 : : /* only non-tautomeric representation of tautomeric */
609 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
610 : : /*================ compare fixed H to previous =====================*/
611 [ # # ]: 0 : eq2prev = bUseMulipliers &&
612 [ # # # # ]: 0 : pINChI && pINChI_Prev && pINChI->nNumberOfAtoms > 0 &&
613 [ # # # # ]: 0 : pINChI_Prev->nNumberOfAtoms == pINChI->nNumberOfAtoms &&
614 : 0 : !memcmp( pINChI_Prev->nNum_H_fixed, pINChI->nNum_H_fixed,
615 [ # # ]: 0 : pINChI_Prev->nNumberOfAtoms * sizeof( pINChI->nNum_H_fixed[0] ) );
616 [ # # ]: 0 : if (eq2prev)
617 : : {
618 : : /* make sure it is not empty */
619 : 0 : eq2prev = 0;
620 [ # # ]: 0 : for (j = 0; j < pINChI_Prev->nNumberOfAtoms; j++)
621 : : {
622 [ # # ]: 0 : if (pINChI_Prev->nNum_H_fixed[j])
623 : : {
624 : 0 : eq2prev = 1;
625 : 0 : break;
626 : : }
627 : : }
628 : : }
629 [ # # ]: 0 : if (eq2prev)
630 : : {
631 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
632 : 0 : continue;
633 : : }
634 : : else
635 : : {
636 : : /* print pINChI_Prev */
637 : : /* delimiter */
638 [ # # ]: 0 : if (bNext++)
639 : : {
640 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
641 : : }
642 [ # # ]: 0 : if (pINChI_Prev)
643 : : {
644 : : /* verify it is not empty */
645 : 0 : bNotEmpty = 0;
646 [ # # ]: 0 : for (j = 0; j < pINChI_Prev->nNumberOfAtoms; j++)
647 : : {
648 [ # # ]: 0 : if (pINChI_Prev->nNum_H_fixed[j])
649 : : {
650 : 0 : bNotEmpty = 1;
651 : 0 : break;
652 : : }
653 : : }
654 [ # # ]: 0 : if (bNotEmpty)
655 : : {
656 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
657 : : /* H-atoms-fixed */
658 : 0 : MakeHString( 0, pINChI_Prev->nNum_H_fixed,
659 : : pINChI_Prev->nNumberOfAtoms,
660 : : strbuf, ATOM_MODE, bOverflow );
661 : : }
662 : : else
663 : : {
664 : 0 : nNumEmpty++;
665 : : }
666 : : }
667 : : }
668 : 0 : pINChI_Prev = pINChI;
669 : 0 : mult = 0; /* we do not know whether the item is empty */
670 : : }
671 [ # # # # ]: 0 : if (nNumEmpty == num_components && strbuf->nUsedLength > nUsedLength0)
672 : : {
673 : 0 : strbuf->nUsedLength = nUsedLength0;
674 : 0 : strbuf->pStr[nUsedLength0] = '\0';
675 : : }
676 : : /*
677 : : if ( nNumEmpty == num_components && tot_len > tot_len_inp ) {
678 : : tot_len = tot_len_inp;
679 : : strbuf->pStr[tot_len] = '\0';
680 : : }
681 : : */
682 : :
683 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
684 : : }
685 : :
686 : : /**
687 : : * @brief Produce double bond stereo substring of the whole structure InChI string.
688 : : *
689 : : * @param pINChISort Pointer to the primary INCHI_SORT structure containing input data.
690 : : * @param pINChISort2 Pointer to the secondary INCHI_SORT structure, used for comparison or additional data.
691 : : * @param strbuf Pointer to an INCHI_IOS_STRING buffer where the output string will be stored.
692 : : * @param bOverflow Pointer to an integer flag that will be set if the output overflows the buffer.
693 : : * @param bOutType Output type flag specifying the format or type of output.
694 : : * @param TAUT_MODE Tautomer mode flag indicating how tautomers are handled.
695 : : * @param num_components Number of components to process.
696 : : * @param bSecondNonTautPass Flag indicating if this is the second pass for non-tautomeric processing.
697 : : * @param bOmitRepetitions Flag to omit repeated entries in the output.
698 : : * @param bUseMulipliers Flag to use multipliers in the output representation.
699 : : * @return Returns number of characters written to strbuf
700 : : */
701 : 0 : int str_Sp2( INCHI_SORT *pINChISort,
702 : : INCHI_SORT *pINChISort2,
703 : : INCHI_IOS_STRING *strbuf,
704 : : int *bOverflow,
705 : : int bOutType,
706 : : int TAUT_MODE,
707 : : int num_components,
708 : : int bSecondNonTautPass,
709 : : int bOmitRepetitions,
710 : : int bUseMulipliers )
711 : : {
712 : : int i, ii, ii2, nUsedLength0;
713 : : INCHI_SORT *is, *is2, *is0, *is20;
714 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
715 : : INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
716 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
717 : : const char *pPrevEquStr, *pCurrEquStr;
718 : : int multPrevEquStr;
719 : :
720 : 0 : pINChI_Taut = NULL;
721 : 0 : pINChI_Prev = NULL;
722 : 0 : pINChI_Taut_Prev = NULL;
723 : 0 : mult = 0;
724 : 0 : bNext = 0;
725 : 0 : is = NULL;
726 : 0 : is2 = NULL;
727 : 0 : is0 = pINChISort;
728 [ # # ]: 0 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
729 : : /* djb-rwth: removing redundant code */
730 : 0 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
731 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
732 : 0 : multPrevEquStr = 0;
733 : 0 : nUsedLength0 = strbuf->nUsedLength;
734 : :
735 : : /* For each connected component ... */
736 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
737 : : {
738 : :
739 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
740 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
741 : : /*================ compare sp2 to previous =====================*/
742 [ # # ]: 0 : if (bSecondNonTautPass)
743 : : {
744 : : /* component that was output on the 1st pass */
745 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
746 : : }
747 : : /*========= if bSecondNonTautPass then compare non-iso non-taut stereo to non-iso taut ========*/
748 : 0 : eq2taut = 0;
749 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
750 : : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Taut)
751 : : {
752 : : Stereo = pINChI->Stereo;
753 : : Stereo_Taut = pINChI_Taut->Stereo;
754 : : eq2taut = Stereo && Stereo_Taut &&
755 : : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
756 : : eq2taut = eq2taut ? ( iiSTEREO | iitNONTAUT ) : 0;
757 : :
758 : : if (!eq2taut &&
759 : : !Eql_INChI_Stereo( Stereo, EQL_SP2, NULL, EQL_EXISTS, 0 ) &&
760 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP2, NULL, EQL_EXISTS, 0 ))
761 : : {
762 : : eq2taut = iiEmpty; /* the current is empty while the preceding (taut) is not */
763 : : }
764 : : }
765 : : #else
766 [ # # # # : 0 : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions)
# # ]
767 : : {
768 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
769 [ # # # # : 0 : ( Stereo = pINChI->Stereo ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
770 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
771 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitNONTAUT ) : 0;
772 : : }
773 : : #endif
774 [ # # ]: 0 : if (eq2taut)
775 : : {
776 : : /* we may be here only in case of the second (non-taut) pass */
777 : : /* current non-taut stereo has been found to be same as tautomeric */
778 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
779 : : {
780 : : /* previous component exists; output it */
781 [ # # ]: 0 : if (bNext++)
782 : : {
783 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
784 : : }
785 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->Stereo ) && Stereo_Prev->nNumberOfStereoBonds > 0)
786 : : {
787 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
788 : :
789 : 0 : MakeStereoString( Stereo_Prev->nBondAtom1, Stereo_Prev->nBondAtom2,
790 : : Stereo_Prev->b_parity,
791 : : 0, Stereo_Prev->nNumberOfStereoBonds,
792 : : strbuf, TAUT_MODE, bOverflow );
793 : : }
794 : : }
795 : : else
796 : : {
797 [ # # # # ]: 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
798 : : {
799 : : /* previous non-taut component exists only in taut list */
800 [ # # ]: 0 : if (bNext++)
801 : : {
802 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
803 : : }
804 : : }
805 : : }
806 : : /* we have found pINChI->Stereo sp2 same as in pINChI_Taut */
807 : : /* output this (current) equivalence as '*', that is, same as tautomeric */
808 : : /* that was printed on the 1st pass. */
809 : 0 : pCurrEquStr = EquString( eq2taut );
810 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
811 : : {
812 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
813 : : {
814 : 0 : multPrevEquStr++;
815 : : }
816 : : else
817 : : {
818 : : /* new EqStr is different; output the previous one */
819 [ # # ]: 0 : if (bNext++)
820 : : {
821 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
822 : : }
823 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
824 : 0 : pPrevEquStr = pCurrEquStr;
825 : 0 : multPrevEquStr = 1;
826 : : }
827 : : }
828 : : else
829 : : {
830 : 0 : pPrevEquStr = pCurrEquStr;
831 : 0 : multPrevEquStr = 1;
832 : : }
833 : 0 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
834 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
835 : 0 : mult = 0;
836 : 0 : eq2tautPrev = 1; /* pINChI_Prev sp2 does not exist */
837 : : }
838 : : else
839 : : {
840 [ # # ]: 0 : if (eq2tautPrev)
841 : : {
842 : : /* at this point pINChI_Prev does not exist; however, pINChI */
843 : : /*might have been discovered and it is different from pINChI_Taut */
844 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
845 : : {
846 : : /* new EqStr is different; output it */
847 [ # # ]: 0 : if (bNext++)
848 : : {
849 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
850 : : }
851 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
852 : 0 : pPrevEquStr = NULL;
853 : 0 : multPrevEquStr = 0;
854 : : }
855 : 0 : eq2tautPrev = 0;
856 : 0 : pINChI_Prev = pINChI;
857 : 0 : pINChI_Taut_Prev = pINChI_Taut;
858 : 0 : mult = 0;
859 : : }
860 : : else
861 : : {
862 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
863 [ # # ]: 0 : eq2prev = bUseMulipliers &&
864 [ # # ]: 0 : pINChI && pINChI_Prev &&
865 [ # # # # : 0 : ( Stereo = pINChI->Stereo ) && ( Stereo_Prev = pINChI_Prev->Stereo ) &&
# # # # ]
866 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Prev, EQL_SP2, 0 );
867 [ # # ]: 0 : if (eq2prev)
868 : : {
869 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
870 : 0 : continue;
871 : : }
872 : : else
873 : : {
874 : : /* pINChI sp2 info is either different or trivial. Output pINChI_Prev anyway */
875 [ # # ]: 0 : if (bNext++)
876 : : {
877 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
878 : : }
879 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
880 : : {
881 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->Stereo ) && Stereo_Prev->nNumberOfStereoBonds > 0)
882 : : {
883 : : /* pINChI_Prev exists and has sp2 info */
884 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
885 : :
886 : 0 : MakeStereoString( Stereo_Prev->nBondAtom1, Stereo_Prev->nBondAtom2,
887 : : Stereo_Prev->b_parity,
888 : : 0, Stereo_Prev->nNumberOfStereoBonds,
889 : : strbuf, TAUT_MODE, bOverflow );
890 : : }
891 : : /* else sp2 info is not present in pINChI_Prev */
892 : : }
893 : : else
894 : : {
895 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
896 : : {
897 [ # # ]: 0 : if (( Stereo_Taut_Prev = pINChI_Taut_Prev->Stereo ) && Stereo_Taut_Prev->nNumberOfStereoBonds > 0)
898 : : {
899 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
900 : : /* and it has non-trivial sp2 info */
901 : : /*
902 : : tot_len += MakeDelim( sIdenticalValues, strbuf, bOverflow);
903 : : */
904 : : ;/* pINChI_Taut_Prev sp2 info was output in the main stereo section */
905 : : }
906 : : else
907 : : {
908 : : ; /* pINChI_Taut_Prev exists and has not sp2 info */
909 : : }
910 : : }
911 : : }
912 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
913 : : else
914 : : {
915 : : int stop = 1; /* <BRKPT> */
916 : : }
917 : : #endif
918 : : }
919 : 0 : pINChI_Prev = pINChI;
920 : 0 : pINChI_Taut_Prev = pINChI_Taut;
921 : 0 : mult = 0; /* we do not know whether the item is empty */
922 : : }
923 : : }
924 : : } /* end of for each connected component ... */
925 : :
926 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
927 : : }
928 : :
929 : : /**
930 : : * @brief Produce tetrahedral stereo substring of the whole structure InChI string.
931 : : *
932 : : * @param pINChISort Pointer to the primary INCHI_SORT structure containing input data.
933 : : * @param pINChISort2 Pointer to the secondary INCHI_SORT structure, used for comparison or additional data.
934 : : * @param strbuf Pointer to an INCHI_IOS_STRING buffer where the output string will be stored.
935 : : * @param bOverflow Pointer to an integer flag that will be set if the output overflows the buffer.
936 : : * @param bOutType Output type flag specifying the format or type of output.
937 : : * @param TAUT_MODE Tautomer mode flag indicating how tautomers are handled.
938 : : * @param num_components The number of components to process.
939 : : * @param bRelRac Flag for relative or racemic stereochemistry.
940 : : * @param bSecondNonTautPass Flag indicating if this is the second pass for non-tautomeric processing.
941 : : * @param bOmitRepetitions Flag to omit repeated entries in the output.
942 : : * @param bUseMulipliers Flag to use multipliers in the output representation.
943 : : * @return int
944 : : */
945 : 42 : int str_Sp3( INCHI_SORT *pINChISort,
946 : : INCHI_SORT *pINChISort2,
947 : : INCHI_IOS_STRING *strbuf,
948 : : int *bOverflow,
949 : : int bOutType,
950 : : int TAUT_MODE,
951 : : int num_components,
952 : : int bRelRac,
953 : : int bSecondNonTautPass,
954 : : int bOmitRepetitions,
955 : : int bUseMulipliers )
956 : : {
957 : : int i, ii, ii2, nUsedLength0;
958 : : INCHI_SORT *is, *is2, *is0, *is20;
959 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
960 : : INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
961 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
962 : : const char *pPrevEquStr, *pCurrEquStr;
963 : : int multPrevEquStr;
964 : 42 : pINChI_Taut = NULL;
965 : 42 : pINChI_Prev = NULL;
966 : 42 : pINChI_Taut_Prev = NULL;
967 : 42 : mult = 0;
968 : 42 : bNext = 0;
969 : 42 : is = NULL;
970 : 42 : is2 = NULL;
971 : 42 : is0 = pINChISort;
972 [ - + ]: 42 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
973 : : /* djb-rwth: removing redundant code */
974 : 42 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
975 : 42 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
976 : 42 : multPrevEquStr = 0;
977 : : #if ( REL_RAC_STEREO_IGN_1_SC == 1 )
978 : : #else
979 : 42 : bRelRac = 0;
980 : : #endif
981 : 42 : nUsedLength0 = strbuf->nUsedLength;
982 : :
983 : : /* For each connected component... */
984 [ + + ]: 136 : for (i = 0; i <= num_components; i++)
985 : : {
986 : :
987 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
988 [ + + - + : 94 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
989 : : /*================ compare sp3 to previous =====================*/
990 [ - + ]: 94 : if (bSecondNonTautPass)
991 : : {
992 : : /* component that was output on the 1st pass */
993 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
994 : : }
995 : : /*========= if bSecondNonTautPass then compare non-iso non-taut stereo to non-iso taut ========*/
996 : 94 : eq2taut = 0;
997 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
998 : : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Taut)
999 : : {
1000 : : Stereo = pINChI->Stereo;
1001 : : Stereo_Taut = pINChI_Taut->Stereo;
1002 : : eq2taut = Stereo && Stereo_Taut &&
1003 : : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
1004 : : eq2taut = eq2taut ? ( iiSTEREO | iitNONTAUT ) : 0;
1005 : : if (!eq2taut &&
1006 : : !Eql_INChI_Stereo( Stereo, EQL_SP3, NULL, EQL_EXISTS, 0 ) &&
1007 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3, NULL, EQL_EXISTS, 0 ))
1008 : : {
1009 : : eq2taut = iiEmpty; /* the current is empty while the preceding (taut) is not */
1010 : : }
1011 : : }
1012 : : #else
1013 [ + - - + : 94 : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions)
- - ]
1014 : : {
1015 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
1016 [ # # # # : 0 : ( Stereo = pINChI->Stereo ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
1017 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
1018 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitNONTAUT ) : 0;
1019 : : }
1020 : : #endif
1021 [ - + ]: 94 : if (eq2taut)
1022 : : {
1023 : : /* we may be here only in case of the second (non-taut) pass */
1024 : : /* current non-taut stereo has been found to be same as tautomeric */
1025 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1026 : : {
1027 : : /* previous component exists; output it */
1028 [ # # ]: 0 : if (bNext++)
1029 : : {
1030 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1031 : : }
1032 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->Stereo ) && Stereo_Prev->nNumberOfStereoCenters > 0)
1033 : : {
1034 : : /* non-empty item */
1035 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1036 : 0 : MakeStereoString( Stereo_Prev->nNumber, NULL,
1037 : : Stereo_Prev->t_parity,0,
1038 : : Stereo_Prev->nNumberOfStereoCenters,
1039 : : strbuf, TAUT_MODE, bOverflow );
1040 : : }
1041 : : }
1042 : : else
1043 [ # # # # ]: 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
1044 : : {
1045 : : /* previous non-taut component exists only in taut list */
1046 [ # # ]: 0 : if (bNext++)
1047 : : {
1048 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1049 : : }
1050 : : }
1051 : : /* we have found pINChI->Stereo sp3 same as in pINChI_Taut */
1052 : : /* output this (current) equivalence as '*', that is, same as tautomeric */
1053 : : /* that was printed on the 1st pass. */
1054 : :
1055 : 0 : pCurrEquStr = EquString( eq2taut );
1056 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1057 : : {
1058 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
1059 : : {
1060 : 0 : multPrevEquStr++;
1061 : : }
1062 : : else
1063 : : {
1064 : : /* new EqStr is different; output it */
1065 [ # # ]: 0 : if (bNext++)
1066 : : {
1067 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1068 : : }
1069 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1070 : 0 : pPrevEquStr = pCurrEquStr;
1071 : 0 : multPrevEquStr = 1;
1072 : : }
1073 : : }
1074 : : else
1075 : : {
1076 : 0 : pPrevEquStr = pCurrEquStr;
1077 : 0 : multPrevEquStr = 1;
1078 : : }
1079 : :
1080 : 0 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
1081 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
1082 : 0 : mult = 0;
1083 : 0 : eq2tautPrev = 1; /* pINChI_Prev sp2 does not exist */
1084 : : }
1085 : : else
1086 : : {
1087 [ + + ]: 94 : if (eq2tautPrev)
1088 : : {
1089 : : /* at this point pINChI_Prev does not exist; however, pINChI */
1090 : : /*might have been discovered and it is different from pINChI_Taut */
1091 [ - + - - ]: 42 : if (multPrevEquStr && pPrevEquStr)
1092 : : {
1093 : : /* new EqStr is different; output it */
1094 [ # # ]: 0 : if (bNext++)
1095 : : {
1096 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1097 : : }
1098 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1099 : 0 : pPrevEquStr = NULL;
1100 : 0 : multPrevEquStr = 0;
1101 : : }
1102 : 42 : eq2tautPrev = 0;
1103 : 42 : pINChI_Prev = pINChI;
1104 : 42 : pINChI_Taut_Prev = pINChI_Taut;
1105 : 42 : mult = 0;
1106 : : }
1107 : : else
1108 : : {
1109 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp3 */
1110 : : /*================ compare sp3 to previous =====================*/
1111 [ + + ]: 52 : eq2prev = bUseMulipliers &&
1112 [ + - ]: 10 : pINChI && pINChI_Prev &&
1113 [ + - + - : 114 : ( Stereo = pINChI->Stereo ) && ( Stereo_Prev = pINChI_Prev->Stereo ) &&
+ - + + ]
1114 : 10 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Prev, EQL_SP3, bRelRac );
1115 [ + + ]: 52 : if (eq2prev)
1116 : : {
1117 : 5 : mult++; /* mult = (number of non-empty equal items)-1 */
1118 : 5 : continue;
1119 : : }
1120 : : else
1121 : : {
1122 [ + + ]: 47 : if (bNext++)
1123 : : {
1124 : 5 : MakeDelim( sCompDelim, strbuf, bOverflow );
1125 : : }
1126 [ + - + - ]: 47 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1127 : : {
1128 [ + - + + ]: 47 : if (( Stereo_Prev = pINChI_Prev->Stereo ) && Stereo_Prev->nNumberOfStereoCenters > bRelRac)
1129 : : {
1130 : : /* pINChI_Prev exists and has sp3 info */
1131 : 46 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1132 : :
1133 : 46 : MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parity,
1134 : : 0, Stereo_Prev->nNumberOfStereoCenters,
1135 : : strbuf, TAUT_MODE, bOverflow );
1136 : : }
1137 : : /* else sp3 info is not present in pINChI_Prev */
1138 : : }
1139 : : else
1140 : : {
1141 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
1142 : : {
1143 [ # # ]: 0 : if (( Stereo_Taut_Prev = pINChI_Taut_Prev->Stereo ) && Stereo_Taut_Prev->nNumberOfStereoCenters > bRelRac)
1144 : : {
1145 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
1146 : : /* and it has non-trivial sp3 info. This info has already been printed in the main section */
1147 : : /*
1148 : : tot_len += MakeDelim( sIdenticalValues, strbuf, bOverflow);
1149 : : */
1150 : : ; /* pINChI_Taut_Prev sp3 info was output in the main stereo section */
1151 : : }
1152 : : else
1153 : : {
1154 : : ; /* pINChI_Taut_Prev exists and has not sp3 info */
1155 : : }
1156 : : }
1157 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
1158 : : else
1159 : : {
1160 : : int stop = 1; /* <BRKPT> */
1161 : : }
1162 : : #endif
1163 : : }
1164 : : }
1165 : 47 : pINChI_Prev = pINChI;
1166 : 47 : pINChI_Taut_Prev = pINChI_Taut;
1167 : 47 : mult = 0; /* we do not know whether the item is empty */
1168 : : }
1169 : : }
1170 : : }
1171 : :
1172 : 42 : return ( strbuf->nUsedLength - nUsedLength0 );
1173 : : }
1174 : :
1175 : : /**
1176 : : * @brief Output absolute stereo inversion substring of the whole structure InChI string
1177 : : * @param pINChISort Pointer to INCHI_SORT array
1178 : : * @param strbuf Pointer to string buffer
1179 : : * @param bOverflow Overflow flag
1180 : : * @param bOutType Output type
1181 : : * @param num_components Number of connected components
1182 : : * @return Length of the added substring (return value '0', '1', or '.' in strbuf)
1183 : : */
1184 : 42 : int str_StereoAbsInv( INCHI_SORT *pINChISort,
1185 : : INCHI_IOS_STRING *strbuf,
1186 : : int *bOverflow,
1187 : : int bOutType,
1188 : : int num_components )
1189 : : {
1190 : : int i, j, ii, nUsedLength0;
1191 : : INCHI_SORT *is, *is0;
1192 : : INChI_Stereo *Stereo;
1193 : : INChI *pINChI;
1194 : :
1195 : 42 : is = NULL;
1196 : 42 : is0 = pINChISort;
1197 : 42 : nUsedLength0 = strbuf->nUsedLength;
1198 : :
1199 : : /* For each connected component... */
1200 [ + - + + ]: 94 : for (i = 0; !*bOverflow && i < num_components; i++)
1201 : : {
1202 : :
1203 : 52 : is = is0 + i;
1204 [ - + - - : 52 : pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
1205 [ + - + - : 52 : if (pINChI && ( Stereo = pINChI->Stereo ) && ( j = Stereo->nCompInv2Abs ))
+ + ]
1206 : : {
1207 [ + + ]: 51 : MakeDelim( j < 0 ? "1" : "0", strbuf, bOverflow );
1208 : : }
1209 : : else
1210 : : {
1211 : 1 : MakeDelim( ".", strbuf, bOverflow );
1212 : : }
1213 : : }
1214 : :
1215 : 42 : return ( strbuf->nUsedLength - nUsedLength0 );
1216 : : }
1217 : :
1218 : :
1219 : : /****************************************************************************
1220 : : Produce isotopic substring of the whole structure InChI string.
1221 : : ****************************************************************************/
1222 : 0 : int str_IsoAtoms( INCHI_SORT *pINChISort,
1223 : : INCHI_SORT *pINChISort2,
1224 : : INCHI_IOS_STRING *strbuf,
1225 : : int *bOverflow,
1226 : : int bOutType,
1227 : : int TAUT_MODE,
1228 : : int num_components,
1229 : : int bAbcNumbers,
1230 : : int bSecondNonTautPass,
1231 : : int bOmitRepetitions,
1232 : : int bUseMulipliers )
1233 : : {
1234 : : int i, ii, ii2, nUsedLength0;
1235 : : INCHI_SORT *is, *is2, *is0, *is20;
1236 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
1237 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
1238 : : const char *pPrevEquStr, *pCurrEquStr;
1239 : : int multPrevEquStr;
1240 : 0 : pINChI_Taut = NULL;
1241 : 0 : pINChI_Prev = NULL;
1242 : 0 : pINChI_Taut_Prev = NULL;
1243 : 0 : mult = 0;
1244 : 0 : bNext = 0;
1245 : 0 : is = NULL;
1246 : 0 : is2 = NULL;
1247 : 0 : is0 = pINChISort;
1248 [ # # ]: 0 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
1249 : : /* djb-rwth: removing redundant code */
1250 : 0 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
1251 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1252 : 0 : multPrevEquStr = 0;
1253 : 0 : nUsedLength0 = strbuf->nUsedLength;
1254 : :
1255 : : /* For each connected component... */
1256 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
1257 : : {
1258 : :
1259 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1260 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1261 : : /*================ compare isotopic info to previous component =====================*/
1262 [ # # ]: 0 : if (bSecondNonTautPass)
1263 : : {
1264 : : /* component that was output on the 1st pass */
1265 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
1266 : : }
1267 : : /*========= if bSecondNonTautPass then compare iso non-taut to taut non-iso ========*/
1268 : 0 : eq2taut = 0;
1269 [ # # # # : 0 : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions)
# # ]
1270 : : {
1271 : 0 : eq2taut = Eql_INChI_Isotopic( pINChI, pINChI_Taut );
1272 [ # # ]: 0 : eq2taut = eq2taut ? ( iiNUMB | iitNONTAUT ) : 0;
1273 : : }
1274 [ # # ]: 0 : if (eq2taut)
1275 : : {
1276 : : /* we may be here only in case of the second (non-taut) pass */
1277 : : /* current non-taut isotopic info has been found to be same as current tautomeric */
1278 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1279 : : {
1280 : : /* previous component exists; output it */
1281 [ # # ]: 0 : if (bNext++)
1282 : : {
1283 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1284 : : }
1285 [ # # # # ]: 0 : if (pINChI_Prev && ( pINChI_Prev->nNumberOfIsotopicAtoms > 0 ||
1286 [ # # ]: 0 : pINChI_Prev->nNumberOfIsotopicTGroups > 0 ))
1287 : : {
1288 : : /* non-empty item */
1289 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1290 : : /* Isotopic atoms */
1291 [ # # # # ]: 0 : if (pINChI_Prev->nNumberOfIsotopicAtoms > 0/* && nStrLen-tot_len > 2*/ && !*bOverflow)
1292 : : { /* dereferenced bOverflow 2004-06-07 */
1293 : 0 : MakeIsoAtomString( pINChI_Prev->IsotopicAtom,
1294 : : pINChI_Prev->nNumberOfIsotopicAtoms,
1295 : : strbuf,
1296 : : TAUT_MODE, bOverflow );
1297 : : }
1298 : : /* Isotopic tautomeric groups */
1299 [ # # ]: 0 : if (pINChI_Prev->nNumberOfIsotopicTGroups > 0 &&
1300 : : /*nStrLen-tot_len > 3 && */
1301 [ # # ]: 0 : !*bOverflow)
1302 : : {
1303 [ # # ]: 0 : MakeDelim( bAbcNumbers ? ITEM_DELIMETER : "(", strbuf, bOverflow );
1304 : 0 : MakeIsoTautString( pINChI_Prev->IsotopicTGroup, pINChI_Prev->nNumberOfIsotopicTGroups,
1305 : : strbuf, TAUT_MODE, bOverflow );
1306 [ # # ]: 0 : if (!bAbcNumbers)
1307 : : {
1308 : 0 : MakeDelim( ")", strbuf, bOverflow );
1309 : : }
1310 : : }
1311 : : }
1312 : : }
1313 : : else
1314 : : {
1315 [ # # # # ]: 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
1316 : : {
1317 : : /* previous non-taut component exists only in taut list */
1318 [ # # ]: 0 : if (bNext++)
1319 : : {
1320 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1321 : : }
1322 : : }
1323 : : }
1324 : : /* we have found pINChI isotopic info to be same as in pINChI_Taut */
1325 : : /* output this (current) equivalence as '*', that is, same as tautomeric */
1326 : : /* that was printed on the 1st pass. */
1327 : 0 : pCurrEquStr = EquString( eq2taut );
1328 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1329 : : {
1330 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
1331 : : {
1332 : 0 : multPrevEquStr++;
1333 : : }
1334 : : else
1335 : : {
1336 : : /* new EqStr is different; output it */
1337 [ # # ]: 0 : if (bNext++)
1338 : : {
1339 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1340 : : }
1341 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1342 : 0 : pPrevEquStr = pCurrEquStr;
1343 : 0 : multPrevEquStr = 1;
1344 : : }
1345 : : }
1346 : : else
1347 : : {
1348 : 0 : pPrevEquStr = pCurrEquStr;
1349 : 0 : multPrevEquStr = 1;
1350 : : }
1351 : 0 : pINChI_Prev = NULL; /* pINChI_Prev isotopic info does not exist since */
1352 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
1353 : 0 : mult = 0;
1354 : 0 : eq2tautPrev = 1; /* pINChI_Prev isotopic info does not exist */
1355 : : }
1356 : : else
1357 [ # # ]: 0 : if (eq2tautPrev)
1358 : : {
1359 : : /* at this point pINChI_Prev does not exist; however, pINChI */
1360 : : /* might have been discovered and it is different from pINChI_Taut */
1361 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1362 : : {
1363 : : /* new EqStr is different; output it */
1364 [ # # ]: 0 : if (bNext++)
1365 : : {
1366 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1367 : : }
1368 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1369 : 0 : pPrevEquStr = NULL;
1370 : 0 : multPrevEquStr = 0;
1371 : : }
1372 : 0 : eq2tautPrev = 0;
1373 : 0 : pINChI_Prev = pINChI;
1374 : 0 : pINChI_Taut_Prev = pINChI_Taut;
1375 : 0 : mult = 0;
1376 : : }
1377 : : else
1378 : : {
1379 : : /*================ compare iso composition to previous =====================*/
1380 : : /* check whether pINChI and pINChI_Prev have non-zero identical isotopic info */
1381 [ # # # # ]: 0 : eq2prev = bUseMulipliers && Eql_INChI_Isotopic( pINChI, pINChI_Prev );
1382 [ # # ]: 0 : if (eq2prev)
1383 : : {
1384 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
1385 : 0 : continue;
1386 : : }
1387 : : else
1388 : : {
1389 : : /* pINChI isotopic info is either different or empty. Output pINChI_Prev anyway */
1390 [ # # ]: 0 : if (bNext++)
1391 : : {
1392 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1393 : : }
1394 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1395 : : {
1396 [ # # ]: 0 : if (( pINChI_Prev->nNumberOfIsotopicAtoms > 0 ||
1397 [ # # ]: 0 : pINChI_Prev->nNumberOfIsotopicTGroups > 0 ))
1398 : : {
1399 : : /* pINChI_Prev exists and has isotopic info */
1400 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1401 : : /* Isotopic atoms */
1402 [ # # ]: 0 : if (pINChI_Prev->nNumberOfIsotopicAtoms > 0 &&
1403 : : /*nStrLen-tot_len > 2 && */
1404 [ # # ]: 0 : !*bOverflow)
1405 : : {
1406 : 0 : MakeIsoAtomString( pINChI_Prev->IsotopicAtom,
1407 : : pINChI_Prev->nNumberOfIsotopicAtoms,
1408 : : strbuf, TAUT_MODE, bOverflow );
1409 : : }
1410 : : /* Isotopic tautomeric groups */
1411 [ # # ]: 0 : if (pINChI_Prev->nNumberOfIsotopicTGroups > 0 &&
1412 : : /*nStrLen-tot_len > 3 && */
1413 [ # # ]: 0 : !*bOverflow)
1414 : : {
1415 [ # # ]: 0 : MakeDelim( bAbcNumbers ? ITEM_DELIMETER : "(", strbuf, bOverflow );
1416 : 0 : MakeIsoTautString( pINChI_Prev->IsotopicTGroup, pINChI_Prev->nNumberOfIsotopicTGroups,
1417 : : strbuf, TAUT_MODE, bOverflow );
1418 [ # # ]: 0 : if (!bAbcNumbers)
1419 : : {
1420 : 0 : MakeDelim( ")", strbuf, bOverflow );
1421 : : }
1422 : : }
1423 : : }
1424 : : /* else isotopic info is not present in pINChI_Prev */
1425 : : }
1426 : : else
1427 : : {
1428 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
1429 : : {
1430 [ # # ]: 0 : if (( pINChI_Taut_Prev->nNumberOfIsotopicAtoms > 0 ||
1431 : 0 : pINChI_Taut_Prev->nNumberOfIsotopicTGroups > 0 ))
1432 : : {
1433 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
1434 : : /* and it has non-trivial isotopic info */
1435 : : /*
1436 : : tot_len += MakeDelim( sIdenticalValues, strbuf, bOverflow);
1437 : : */
1438 : : ;/* pINChI_Taut_Prev isotopic info was output in the main isotopic section */
1439 : : }
1440 : : else
1441 : : {
1442 : : ; /* pINChI_Taut_Prev exists and has not isotopic info */
1443 : : }
1444 : : }
1445 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
1446 : : else
1447 : : {
1448 : : int stop = 1; /* <BRKPT> */
1449 : : }
1450 : : #endif
1451 : : }
1452 : : }
1453 : : /* Fix17: moved here 2004-10-08 */
1454 : 0 : pINChI_Prev = pINChI;
1455 : 0 : pINChI_Taut_Prev = pINChI_Taut;
1456 : 0 : mult = 0; /* we do not know whether the item is empty */
1457 : : }
1458 : : /* Fix17: moved from here 2004-10-08
1459 : : pINChI_Prev = pINChI;
1460 : : pINChI_Taut_Prev = pINChI_Taut;
1461 : : mult = 0;
1462 : : */
1463 : : }
1464 : :
1465 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
1466 : : }
1467 : :
1468 : :
1469 : : /****************************************************************************
1470 : : Produce isotopic-dbonds stereo substring of the whole structure InChI string.
1471 : : ****************************************************************************/
1472 : 0 : int str_IsoSp2( INCHI_SORT *pINChISort,
1473 : : INCHI_SORT *pINChISort2,
1474 : : INCHI_IOS_STRING *strbuf,
1475 : : int *bOverflow,
1476 : : int bOutType,
1477 : : int TAUT_MODE,
1478 : : int num_components,
1479 : : int bSecondNonTautPass,
1480 : : int bOmitRepetitions,
1481 : : int bUseMulipliers )
1482 : : {
1483 : : int i, ii, ii2, nUsedLength0;
1484 : : INCHI_SORT *is, *is2, *is0, *is20;
1485 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
1486 : : INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
1487 : 0 : int mult, eq2prev, eq2taut, eq2tautPrev = 1, bNext; /* djb-rwth: initialisation required to avoid garbage values */
1488 : : const char *pPrevEquStr, *pCurrEquStr;
1489 : : int multPrevEquStr;
1490 : 0 : pINChI_Taut = NULL;
1491 : 0 : pINChI_Prev = NULL;
1492 : 0 : pINChI_Taut_Prev = NULL;
1493 : 0 : mult = 0;
1494 : 0 : bNext = 0;
1495 : 0 : is = NULL;
1496 : 0 : is2 = NULL;
1497 : 0 : is0 = pINChISort;
1498 [ # # ]: 0 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
1499 : : /* djb-rwth: removing redundant code */
1500 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1501 : 0 : multPrevEquStr = 0;
1502 : 0 : nUsedLength0 = strbuf->nUsedLength;
1503 : :
1504 : : /* For each connected component... */
1505 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
1506 : : {
1507 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1508 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1509 : : /*================ compare sp2 to previous =====================*/
1510 [ # # ]: 0 : if (bSecondNonTautPass)
1511 : : {
1512 : : /* component that was output on the 1st pass */
1513 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
1514 : : }
1515 : 0 : eq2taut = 0;
1516 : : /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
1517 [ # # # # ]: 0 : if (bSecondNonTautPass && bOmitRepetitions)
1518 : : {
1519 : : /* compare non-tautomeric isotopic to:
1520 : : * a) non-tautomeric non-isotopic
1521 : : * b) tautomeric non-isotopic
1522 : : * c) tautomeric isotopic
1523 : : */
1524 : : /* a) compare non-tautomeric isotopic to non-tautomeric non-isotopic */
1525 [ # # ]: 0 : if (!eq2taut)
1526 : : {
1527 : 0 : eq2taut = pINChI &&
1528 : : /* non-taut isotopic */ /* non-taut non-isotopic */
1529 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
1530 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
1531 : : /* stereo isotopic non-taut = non-taut (stereo) */
1532 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO | iitNONTAUT | iiEq2NONTAUT ) : 0;
1533 : : }
1534 : : /* b) compare non-tautomeric isotopic to tautomeric non-isotopic */
1535 [ # # ]: 0 : if (!eq2taut)
1536 : : {
1537 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
1538 : : /* non-taut isotopic */ /* taut non-isotopic */
1539 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
1540 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
1541 : : /* stereo isotopic non-taut = taut (stereo) */
1542 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO | iitNONTAUT ) : 0;
1543 : : }
1544 : : /* c) compare non-tautomeric isotopic to tautomeric isotopic */
1545 [ # # # # : 0 : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions)
# # ]
1546 : : {
1547 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
1548 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) &&
# # # # ]
1549 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
1550 : : /* stereo isotopic non-taut = isotopic taut (stereo) */
1551 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO | iitNONTAUT | iiEq2ISO ) : 0;
1552 : : }
1553 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
1554 : : if (!eq2taut && pINChI && !( ( Stereo = pINChI->StereoIsotopic ) &&
1555 : : Eql_INChI_Stereo( Stereo, EQL_SP2, NULL, EQL_EXISTS, 0 ) ))
1556 : : {
1557 : : /* component has no stereo; check whether it has stereo in the preceding layers */
1558 : : if (pINChI_Taut && ( Stereo_Taut = pINChI_Taut->Stereo ) && /* F is not empty */
1559 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP2, NULL, EQL_EXISTS, 0 ) ||
1560 : : !( pINChI_Taut && ( Stereo_Taut = pINChI_Taut->Stereo ) && /* M is empty and ... */
1561 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP2, NULL, EQL_EXISTS, 0 ) ) &&
1562 : : ( pINChI_Taut && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) && /* ... MI is not empty */
1563 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP2, NULL, EQL_EXISTS, 0 ) ))
1564 : : {
1565 : :
1566 : : eq2taut = iiEmpty; /* the component has stereo in the preceding layer */
1567 : : }
1568 : : }
1569 : : #endif
1570 : : }
1571 : : else
1572 : : {
1573 : : /*========= if not bSecondNonTautPass then compare iso taut stereo to non-iso taut ========*/
1574 [ # # # # ]: 0 : if (!bSecondNonTautPass && bOmitRepetitions)
1575 : : {
1576 : : /* compare tautomeric isotopic to tautomeric non-isotopic */
1577 [ # # ]: 0 : if (!eq2taut)
1578 : : {
1579 : 0 : eq2taut = pINChI &&
1580 : : /* taut isotopic */ /* taut non-isotopic */
1581 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
1582 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
1583 : : /* stereo isotopic taut = taut (stereo) */
1584 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO ) : 0;
1585 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
1586 : : if (!eq2taut && pINChI && !( ( Stereo = pINChI->StereoIsotopic ) &&
1587 : : Eql_INChI_Stereo( Stereo, EQL_SP2, NULL, EQL_EXISTS, 0 ) ))
1588 : : {
1589 : : /* component has no MI stereo; check whether it has stereo in the preceding layer M */
1590 : : if (( Stereo_Taut = pINChI->Stereo ) &&
1591 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP2, NULL, EQL_EXISTS, 0 ))
1592 : : {
1593 : : eq2taut = iiEmpty; /* the component has stereo in the preceding layer */
1594 : : }
1595 : : }
1596 : : #endif
1597 : : }
1598 : : }
1599 : : }
1600 [ # # ]: 0 : if (eq2taut)
1601 : : {
1602 : : /* we may be here only in case of the current layer found equal in another layer the same component */
1603 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1604 : : {
1605 : : /* previous component exists; output it before output the current component */
1606 [ # # ]: 0 : if (bNext++)
1607 : : {
1608 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1609 : : }
1610 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->StereoIsotopic ) && Stereo_Prev->nNumberOfStereoBonds > 0)
1611 : : {
1612 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1613 : :
1614 : 0 : MakeStereoString( Stereo_Prev->nBondAtom1, Stereo_Prev->nBondAtom2,
1615 : : Stereo_Prev->b_parity,
1616 : : 0, Stereo_Prev->nNumberOfStereoBonds,
1617 : : strbuf, TAUT_MODE, bOverflow );
1618 : : }
1619 : : }
1620 : : else
1621 : : {
1622 [ # # # # ]: 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
1623 : : {
1624 : : /* previous non-taut component exists only in taut list */
1625 [ # # ]: 0 : if (bNext++)
1626 : : {
1627 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1628 : : }
1629 : : /* do not output stereo of non-tautomeric in non-taut layer: it has been output in the main layer */
1630 : : }
1631 : : }
1632 : : /* we have found another (previously printed) layer of the current component equal to this layer */
1633 : : /* output this (current) equivalence mark = EquString(eq2taut) */
1634 : 0 : pCurrEquStr = EquString( eq2taut );
1635 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1636 : : {
1637 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
1638 : : {
1639 : 0 : multPrevEquStr++;
1640 : : }
1641 : : else
1642 : : {
1643 : : /* new EqStr is different; output it */
1644 [ # # ]: 0 : if (bNext++)
1645 : : {
1646 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1647 : : }
1648 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1649 : 0 : pPrevEquStr = pCurrEquStr;
1650 : 0 : multPrevEquStr = 1;
1651 : : }
1652 : : }
1653 : : else
1654 : : {
1655 : 0 : pPrevEquStr = pCurrEquStr;
1656 : 0 : multPrevEquStr = 1;
1657 : : }
1658 : 0 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
1659 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
1660 : 0 : mult = 0;
1661 : 0 : eq2tautPrev = 1; /* pINChI_Prev and pINChI_Taut_Prev have already been */
1662 : : }
1663 : : else
1664 : : {
1665 [ # # ]: 0 : if (eq2tautPrev)
1666 : : {
1667 : : /* at this point pINChI_Prev does not exist; however, pINChI */
1668 : : /*might have been discovered and it is different from pINChI_Taut */
1669 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1670 : : {
1671 : : /* new EqStr is different; output it */
1672 [ # # ]: 0 : if (bNext++)
1673 : : {
1674 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1675 : : }
1676 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1677 : 0 : pPrevEquStr = NULL;
1678 : 0 : multPrevEquStr = 0;
1679 : : }
1680 : 0 : eq2tautPrev = 0;
1681 : 0 : pINChI_Prev = pINChI;
1682 : 0 : pINChI_Taut_Prev = pINChI_Taut;
1683 : 0 : mult = 0;
1684 : : }
1685 : : else
1686 : : {
1687 : : /* current layer is different from previously printed layers of the current component */
1688 : : /* compare the current layer to this layer of the previous component: */
1689 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
1690 : : /*================ compare iso sp2 to previous =====================*/
1691 [ # # ]: 0 : eq2prev = bUseMulipliers &&
1692 [ # # ]: 0 : pINChI && pINChI_Prev &&
1693 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Prev = pINChI_Prev->StereoIsotopic ) &&
# # # # ]
1694 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Prev, EQL_SP2, 0 );
1695 [ # # ]: 0 : if (eq2prev)
1696 : : {
1697 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
1698 : 0 : continue;
1699 : : }
1700 : : else
1701 : : {
1702 : : /* the current layer is different from this layer of the previous component */
1703 : : /* therefore print the current layer */
1704 [ # # ]: 0 : if (bNext++)
1705 : : {
1706 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1707 : : }
1708 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1709 : : {
1710 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->StereoIsotopic ) && Stereo_Prev->nNumberOfStereoBonds > 0)
1711 : : {
1712 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1713 : :
1714 : 0 : MakeStereoString( Stereo_Prev->nBondAtom1, Stereo_Prev->nBondAtom2,
1715 : : Stereo_Prev->b_parity,
1716 : : 0, Stereo_Prev->nNumberOfStereoBonds,
1717 : : strbuf, TAUT_MODE, bOverflow );
1718 : : }
1719 : : /* else sp2 info is not present in pINChI_Prev */
1720 : : }
1721 : : else
1722 : : {/* do not print pINChI_Prev because it either do not exist of have already been printed */
1723 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
1724 : : {
1725 [ # # ]: 0 : if (( Stereo_Taut_Prev = pINChI_Taut_Prev->StereoIsotopic ) && Stereo_Taut_Prev->nNumberOfStereoBonds > 0)
1726 : : {
1727 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
1728 : : /* and it has non-trivial sp2 info */
1729 : : /*
1730 : : tot_len += MakeDelim( sIdenticalValues, strbuf, bOverflow);
1731 : : */
1732 : : ;/* pINChI_Taut_Prev sp3 info was output in the main stereo section */
1733 : : }
1734 : : else
1735 : : {
1736 : : ; /* pINChI_Taut_Prev exists and has not sp2 info */
1737 : : }
1738 : : }
1739 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
1740 : : else
1741 : : {
1742 : : int stop = 1; /* <BRKPT> */
1743 : : }
1744 : : #endif
1745 : : }
1746 : : }
1747 : 0 : pINChI_Prev = pINChI;
1748 : 0 : pINChI_Taut_Prev = pINChI_Taut;
1749 : 0 : mult = 0; /* we do not know whether the item is empty */
1750 : : }
1751 : : }
1752 : : }
1753 : :
1754 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
1755 : : }
1756 : :
1757 : :
1758 : : /****************************************************************************
1759 : : Produce isotopic-tetr stereo substring of the whole structure InChI string.
1760 : : ****************************************************************************/
1761 : 0 : int str_IsoSp3( INCHI_SORT *pINChISort,
1762 : : INCHI_SORT *pINChISort2,
1763 : : INCHI_IOS_STRING *strbuf,
1764 : : int *bOverflow,
1765 : : int bOutType,
1766 : : int TAUT_MODE,
1767 : : int num_components,
1768 : : int bRelRac,
1769 : : int bSecondNonTautPass,
1770 : : int bOmitRepetitions,
1771 : : int bUseMulipliers )
1772 : : {
1773 : : int i, ii, ii2, nUsedLength0;
1774 : : INCHI_SORT *is, *is2, *is0, *is20;
1775 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
1776 : : INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
1777 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
1778 : : const char *pPrevEquStr, *pCurrEquStr;
1779 : : int multPrevEquStr;
1780 : 0 : pINChI_Taut = NULL;
1781 : 0 : pINChI_Prev = NULL;
1782 : 0 : pINChI_Taut_Prev = NULL;
1783 : 0 : mult = 0;
1784 : 0 : bNext = 0;
1785 : 0 : is = NULL;
1786 : 0 : is2 = NULL;
1787 : 0 : is0 = pINChISort;
1788 [ # # ]: 0 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
1789 : : /* djb-rwth: removing redundant code */
1790 : 0 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
1791 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1792 : 0 : multPrevEquStr = 0;
1793 : : #if ( REL_RAC_STEREO_IGN_1_SC == 1 )
1794 : : #else
1795 : 0 : bRelRac = 0;
1796 : : #endif
1797 : 0 : nUsedLength0 = strbuf->nUsedLength;
1798 : :
1799 : : /* For each connected component... */
1800 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
1801 : : {
1802 : :
1803 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1804 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1805 : : /*================ compare sp2 to previous =====================*/
1806 [ # # ]: 0 : if (bSecondNonTautPass)
1807 : : {
1808 : : /* component that was output on the 1st pass */
1809 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
1810 : : }
1811 : 0 : eq2taut = 0;
1812 : : /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
1813 [ # # # # ]: 0 : if (bSecondNonTautPass && bOmitRepetitions)
1814 : : {
1815 : : /* compare non-tautomeric isotopic to:
1816 : : * a) non-tautomeric non-isotopic
1817 : : * b) tautomeric non-isotopic
1818 : : * c) tautomeric isotopic
1819 : : */
1820 : : /* a) compare non-tautomeric isotopic to non-tautomeric non-isotopic */
1821 [ # # ]: 0 : if (!eq2taut)
1822 : : {
1823 : 0 : eq2taut = pINChI && /* non-taut isotopic */ /* non-taut non-isotopic */
1824 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
1825 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
1826 : : /* stereo isotopic non-taut = non-taut (stereo) */
1827 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO | iitNONTAUT | iiEq2NONTAUT ) : 0;
1828 : : }
1829 : : /* b) compare non-tautomeric isotopic to tautomeric non-isotopic */
1830 [ # # ]: 0 : if (!eq2taut)
1831 : : {
1832 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
1833 : : /* non-taut isotopic */ /* taut non-isotopic */
1834 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
1835 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
1836 : : /* stereo isotopic non-taut = taut (stereo) */
1837 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO | iitNONTAUT ) : 0;
1838 : : }
1839 : : /* c) compare non-tautomeric isotopic to tautomeric isotopic */
1840 [ # # # # : 0 : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions)
# # ]
1841 : : {
1842 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
1843 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) &&
# # # # ]
1844 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
1845 : : /* stereo isotopic non-taut = isotopic taut (stereo) */
1846 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO | iitNONTAUT | iiEq2ISO ) : 0;
1847 : : }
1848 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
1849 : : if (!eq2taut && pINChI && !( ( Stereo = pINChI->StereoIsotopic ) &&
1850 : : Eql_INChI_Stereo( Stereo, EQL_SP3, NULL, EQL_EXISTS, 0 ) ))
1851 : : {
1852 : : /* component has no stereo; check whether it has stereo in the preceding layers */
1853 : : if (pINChI_Taut && ( Stereo_Taut = pINChI_Taut->Stereo ) && /* F is not empty */
1854 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3, NULL, EQL_EXISTS, 0 ) ||
1855 : : !( pINChI_Taut && ( Stereo_Taut = pINChI_Taut->Stereo ) && /* M is empty and ... */
1856 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3, NULL, EQL_EXISTS, 0 ) ) &&
1857 : : ( pINChI_Taut && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) && /* ... MI is not empty */
1858 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3, NULL, EQL_EXISTS, 0 ) ))
1859 : : {
1860 : :
1861 : : eq2taut = iiEmpty; /* the component has stereo in the preceding layer */
1862 : : }
1863 : : }
1864 : : #endif
1865 : : }
1866 : : else
1867 : : {
1868 : : /*========= if not bSecondNonTautPass then compare iso taut stereo to non-iso taut ========*/
1869 [ # # # # ]: 0 : if (!bSecondNonTautPass && bOmitRepetitions)
1870 : : {
1871 : : /* compare tautomeric isotopic to tautomeric non-isotopic */
1872 [ # # ]: 0 : if (!eq2taut)
1873 : : {
1874 : 0 : eq2taut = pINChI &&
1875 : : /* taut isotopic */ /* taut non-isotopic */
1876 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
1877 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
1878 : : /* stereo isotopic taut = taut (stereo) */
1879 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO ) : 0;
1880 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
1881 : : if (!eq2taut && pINChI && !( ( Stereo = pINChI->StereoIsotopic ) &&
1882 : : Eql_INChI_Stereo( Stereo, EQL_SP3, NULL, EQL_EXISTS, 0 ) ))
1883 : : {
1884 : : /* component has no MI stereo; check whether it has stereo in the preceding layer M */
1885 : : if (( Stereo_Taut = pINChI->Stereo ) &&
1886 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3, NULL, EQL_EXISTS, 0 ))
1887 : : {
1888 : : eq2taut = iiEmpty; /* the component has stereo in the preceding layer */
1889 : : }
1890 : : }
1891 : : #endif
1892 : : }
1893 : : }
1894 : : }
1895 [ # # ]: 0 : if (eq2taut)
1896 : : {
1897 : : /* we may be here only in case of the current layer found equal in another layer the same component */
1898 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1899 : : {
1900 : : /* previous component exists; output it before output the current component */
1901 [ # # ]: 0 : if (bNext++)
1902 : : {
1903 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1904 : : }
1905 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->StereoIsotopic ) && Stereo_Prev->nNumberOfStereoCenters > bRelRac)
1906 : : {
1907 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1908 : :
1909 : 0 : MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parity,
1910 : : 0, Stereo_Prev->nNumberOfStereoCenters,
1911 : : strbuf, TAUT_MODE, bOverflow );
1912 : : }
1913 : : }
1914 : : else
1915 : : {
1916 [ # # # # ]: 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
1917 : : {
1918 : : /* previous non-taut component exists only in taut list */
1919 [ # # ]: 0 : if (bNext++)
1920 : : {
1921 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1922 : : }
1923 : : /* do not output stereo of non-tautomeric in non-taut layer: it has been output in the main layer */
1924 : : }
1925 : : }
1926 : : /* we have found another (previously printed) layer of the current component equal to this layer */
1927 : : /* output this (current) equivalence mark = EquString(eq2taut) */
1928 : 0 : pCurrEquStr = EquString( eq2taut );
1929 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1930 : : {
1931 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
1932 : : {
1933 : 0 : multPrevEquStr++;
1934 : : }
1935 : : else
1936 : : {
1937 : : /* new EqStr is different; output it */
1938 [ # # ]: 0 : if (bNext++)
1939 : : {
1940 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1941 : : }
1942 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1943 : 0 : pPrevEquStr = pCurrEquStr;
1944 : 0 : multPrevEquStr = 1;
1945 : : }
1946 : : }
1947 : : else
1948 : : {
1949 : 0 : pPrevEquStr = pCurrEquStr;
1950 : 0 : multPrevEquStr = 1;
1951 : : }
1952 : 0 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
1953 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
1954 : 0 : mult = 0;
1955 : 0 : eq2tautPrev = 1; /* pINChI_Prev and pINChI_Taut_Prev have already been output */
1956 : : }
1957 : : else
1958 : : {
1959 [ # # ]: 0 : if (eq2tautPrev)
1960 : : {
1961 : : /* at this point pINChI_Prev does not exist; however, pINChI */
1962 : : /*might have been discovered and it is different from pINChI_Taut */
1963 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1964 : : {
1965 : : /* new EqStr is different; output it */
1966 [ # # ]: 0 : if (bNext++)
1967 : : {
1968 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1969 : : }
1970 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1971 : 0 : pPrevEquStr = NULL;
1972 : 0 : multPrevEquStr = 0;
1973 : : }
1974 : 0 : eq2tautPrev = 0;
1975 : 0 : pINChI_Prev = pINChI;
1976 : 0 : pINChI_Taut_Prev = pINChI_Taut;
1977 : 0 : mult = 0;
1978 : : }
1979 : : else
1980 : : {
1981 : : /* current layer is different from previously printed layers of the current component */
1982 : : /* compare the current layer to this layer of the previous component: */
1983 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
1984 : : /*================ compare iso sp3 to previous =====================*/
1985 [ # # # # ]: 0 : eq2prev = bUseMulipliers && pINChI && pINChI_Prev &&
1986 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Prev = pINChI_Prev->StereoIsotopic ) &&
# # # # ]
1987 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Prev, EQL_SP3, bRelRac );
1988 [ # # ]: 0 : if (eq2prev)
1989 : : {
1990 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
1991 : 0 : continue;
1992 : : }
1993 : : else
1994 : : {
1995 [ # # ]: 0 : if (bNext++)
1996 : : {
1997 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1998 : : }
1999 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
2000 : : {
2001 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->StereoIsotopic ) && Stereo_Prev->nNumberOfStereoCenters > bRelRac)
2002 : : {
2003 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
2004 : :
2005 : 0 : MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parity,
2006 : : 0, Stereo_Prev->nNumberOfStereoCenters,
2007 : : strbuf, TAUT_MODE, bOverflow );
2008 : : }
2009 : : /* else sp3 info is not present in pINChI_Prev */
2010 : : }
2011 : : else
2012 : : /* do not print pINChI_Prev because it either do not exist of have already been printed */
2013 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
2014 : : {
2015 [ # # ]: 0 : if (( Stereo_Taut_Prev = pINChI_Taut_Prev->StereoIsotopic ) && Stereo_Taut_Prev->nNumberOfStereoCenters > bRelRac)
2016 : : {
2017 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
2018 : : /* and it has non-trivial sp2 info */
2019 : : /*
2020 : : tot_len += MakeDelim( sIdenticalValues, strbuf, bOverflow);
2021 : : */
2022 : : ;/* pINChI_Taut_Prev sp3 info was output in the main stereo section */
2023 : : }
2024 : : else
2025 : : {
2026 : : ; /* pINChI_Taut_Prev exists and has not sp3 info */
2027 : : }
2028 : : }
2029 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
2030 : : else
2031 : : {
2032 : : int stop = 1; /* <BRKPT> */
2033 : : }
2034 : : #endif
2035 : : }
2036 : 0 : pINChI_Prev = pINChI;
2037 : 0 : pINChI_Taut_Prev = pINChI_Taut;
2038 : 0 : mult = 0; /* we do not know whether the item is empty */
2039 : : }
2040 : : }
2041 : : }
2042 : :
2043 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
2044 : : }
2045 : :
2046 : :
2047 : : /****************************************************************************
2048 : : Output isotopic abs stero inversion substring
2049 : : of the whole structure InChI string
2050 : : ****************************************************************************/
2051 : 0 : int str_IsoStereoAbsInv( INCHI_SORT *pINChISort,
2052 : : INCHI_IOS_STRING *strbuf,
2053 : : int *bOverflow,
2054 : : int bOutType,
2055 : : int num_components )
2056 : : {
2057 : : int i, j, ii, nUsedLength0;
2058 : : INCHI_SORT *is, *is0;
2059 : : INChI_Stereo *Stereo;
2060 : : INChI *pINChI;
2061 : :
2062 : 0 : is = NULL;
2063 : 0 : is0 = pINChISort;
2064 : 0 : nUsedLength0 = strbuf->nUsedLength;
2065 : :
2066 : : /* For each connected component... */
2067 [ # # # # ]: 0 : for (i = 0; !*bOverflow && i < num_components; i++)
2068 : : {
2069 : 0 : is = is0 + i;
2070 [ # # # # : 0 : pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) )
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
2071 : : ? is->pINChI[ii]
2072 [ # # ]: 0 : : NULL;
2073 [ # # ]: 0 : if (pINChI &&
2074 [ # # ]: 0 : ( Stereo = pINChI->StereoIsotopic ) &&
2075 [ # # ]: 0 : ( j = Stereo->nCompInv2Abs ))
2076 : : {
2077 [ # # ]: 0 : MakeDelim( j < 0 ? "1" : "0", strbuf, bOverflow );
2078 : : }
2079 : : else
2080 : : {
2081 : 0 : MakeDelim( ".", strbuf, bOverflow );
2082 : : }
2083 : : }
2084 : :
2085 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
2086 : : }
2087 : :
2088 : :
2089 : :
2090 : : /*
2091 : : Generate AuxInfo substrings
2092 : : */
2093 : :
2094 : :
2095 : :
2096 : : /****************************************************************************
2097 : : Produce equivalence substring of AuxInfo
2098 : : ****************************************************************************/
2099 : 21 : int str_AuxEqu( INCHI_SORT *pINChISort,
2100 : : INCHI_SORT *pINChISort2,
2101 : : INCHI_IOS_STRING *strbuf,
2102 : : int *bOverflow,
2103 : : int bOutType,
2104 : : int TAUT_MODE,
2105 : : int num_components,
2106 : : int bSecondNonTautPass,
2107 : : int bOmitRepetitions,
2108 : : int bUseMulipliers )
2109 : : {
2110 : : int i, ii, ii2, nUsedLength0;
2111 : : INCHI_SORT *is, *is2, *is0, *is20;
2112 : 21 : INChI_Aux *pINChI_Aux = NULL, *pINChI_Aux_Prev, *pINChI_Aux_Taut, *pINChI_Aux_Taut_Prev;
2113 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
2114 : : const char *pPrevEquStr, *pCurrEquStr;
2115 : : int multPrevEquStr;
2116 : 21 : pINChI_Aux_Prev = NULL;
2117 : 21 : pINChI_Aux_Taut = NULL;
2118 : 21 : pINChI_Aux_Taut_Prev = NULL;
2119 : :
2120 : 21 : mult = 0;
2121 : 21 : bNext = 0;
2122 : 21 : is = NULL;
2123 : 21 : is2 = NULL;
2124 : 21 : is0 = pINChISort;
2125 [ - + ]: 21 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
2126 : : /* djb-rwth: removing redundant code */
2127 : 21 : eq2tautPrev = 1; /* pINChI_Aux_Prev (previous pINChI_Aux) does not exist */
2128 : 21 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
2129 : 21 : multPrevEquStr = 0;
2130 : 21 : nUsedLength0 = strbuf->nUsedLength;
2131 : :
2132 : : /* For each connected component... */
2133 [ + + ]: 81 : for (i = 0; i <= num_components; i++)
2134 : : {
2135 : :
2136 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2137 [ + + - + : 60 : pINChI_Aux = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI_Aux[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
2138 [ - + ]: 60 : if (bSecondNonTautPass)
2139 : : {
2140 : : /* component that was output on the 1st pass */
2141 [ # # # # : 0 : pINChI_Aux_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI_Aux[ii2] : NULL;
# # # # #
# # # ]
2142 : : }
2143 : : /*================ compare non-iso non-taut equivalence info to non-iso taut ========*/
2144 [ - + - - : 60 : eq2taut = bSecondNonTautPass && bOmitRepetitions &&
- - ]
2145 : 0 : Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU, pINChI_Aux_Taut, EQL_EQU );
2146 [ - + ]: 60 : eq2taut = eq2taut ? ( iiEQU | iitNONTAUT ) : 0;
2147 [ - + ]: 60 : if (eq2taut)
2148 : : {
2149 : : /* we may be here only in case of the second (non-taut) pass */
2150 : : /* current non-taut equivalence has been found to be same as tautomeric */
2151 [ # # # # ]: 0 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
2152 : : {
2153 : : /* previous component exists */
2154 [ # # ]: 0 : if (bNext++)
2155 : : {
2156 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2157 : : }
2158 [ # # ]: 0 : if (bHasEquString( pINChI_Aux_Prev->nConstitEquNumbers, pINChI_Aux_Prev->nNumberOfAtoms ))
2159 : : {
2160 : : /* output previous component(s) equivalence since it was found to be non-trivial */
2161 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
2162 : 0 : MakeEquString( pINChI_Aux_Prev->nConstitEquNumbers,
2163 : : pINChI_Aux_Prev->nNumberOfAtoms,
2164 : : 0, strbuf, TAUT_MODE, bOverflow );
2165 : : }
2166 : : else
2167 : : {
2168 : : ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
2169 : : }
2170 : : }
2171 : : else
2172 [ # # # # ]: 0 : if (pINChI_Aux_Taut_Prev && pINChI_Aux_Taut_Prev->nNumberOfAtoms)
2173 : : {
2174 : : /* previous non-taut component exists only in taut list */
2175 [ # # ]: 0 : if (bNext++)
2176 : : {
2177 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2178 : : }
2179 : : }
2180 : : /* we have found pINChI_Aux->nConstitEquNumbers same as in pINChI_Aux_Taut */
2181 : : /* output this (current) equivalence as '*', that is, same as tautomeric */
2182 : : /* that was printed on the 1st pass. */
2183 : 0 : pCurrEquStr = EquString( eq2taut );
2184 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2185 : : {
2186 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
2187 : : {
2188 : 0 : multPrevEquStr++;
2189 : : }
2190 : : else
2191 : : {
2192 : : /* new EqStr is different; output it */
2193 [ # # ]: 0 : if (bNext++)
2194 : : {
2195 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2196 : : }
2197 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2198 : 0 : pPrevEquStr = pCurrEquStr;
2199 : 0 : multPrevEquStr = 1;
2200 : : }
2201 : : }
2202 : : else
2203 : : {
2204 : 0 : pPrevEquStr = pCurrEquStr;
2205 : 0 : multPrevEquStr = 1;
2206 : : }
2207 : 0 : pINChI_Aux_Prev = NULL; /* pINChI_Aux_Prev does not exist since */
2208 : 0 : pINChI_Aux_Taut_Prev = NULL; /* pINChI_Aux has just been printed */
2209 : 0 : mult = 0;
2210 : 0 : eq2tautPrev = 1;
2211 : : }
2212 : : else
2213 : : {
2214 [ + + ]: 60 : if (eq2tautPrev)
2215 : : {
2216 : : /* at this point pINChI_Aux_Prev does not exist; however, pINChI_Aux */
2217 : : /*might have been discovered and it is different from pINChI_Aux_Taut */
2218 [ - + - - ]: 21 : if (multPrevEquStr && pPrevEquStr)
2219 : : {
2220 : : /* new EqStr is different; output it */
2221 [ # # ]: 0 : if (bNext++)
2222 : : {
2223 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2224 : : }
2225 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2226 : 0 : pPrevEquStr = NULL;
2227 : 0 : multPrevEquStr = 0;
2228 : : }
2229 : 21 : eq2tautPrev = 0;
2230 : 21 : pINChI_Aux_Prev = pINChI_Aux;
2231 : 21 : pINChI_Aux_Taut_Prev = pINChI_Aux_Taut;
2232 : 21 : mult = 0;
2233 : : }
2234 : : else
2235 : : {
2236 : : /* check whether pINChI_Aux and pINChI_Aux_Prev have identical non-trivial equivalence info */
2237 [ + - + + ]: 78 : eq2prev = bUseMulipliers &&
2238 : 39 : Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU, pINChI_Aux_Prev, EQL_EQU );
2239 [ + + ]: 39 : if (eq2prev)
2240 : : {
2241 : : /* eq. info is same and non-trivial */
2242 : 2 : mult++; /* mult = (number of non-empty equal items)-1 */
2243 : 2 : continue;
2244 : : }
2245 : : else
2246 : : {
2247 : : /* pINChI_Aux eq. info is either different or trivial. Output pINChI_Aux_Prev anyway */
2248 [ + + ]: 37 : if (bNext++)
2249 : : {
2250 : 16 : MakeDelim( sCompDelim, strbuf, bOverflow );
2251 : : }
2252 [ + - + - ]: 37 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
2253 : : {
2254 [ + + ]: 60 : if (bHasEquString( pINChI_Aux_Prev->nConstitEquNumbers, pINChI_Aux_Prev->nNumberOfAtoms ))
2255 : : {
2256 : : /* pINChI_Aux_Prev exists and has equivalence info */
2257 : 23 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
2258 : 23 : MakeEquString( pINChI_Aux_Prev->nConstitEquNumbers, pINChI_Aux_Prev->nNumberOfAtoms, 0,
2259 : : strbuf, TAUT_MODE, bOverflow );
2260 : : }
2261 : : else
2262 : : {
2263 : : ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
2264 : : }
2265 : : }
2266 : :
2267 : : else
2268 : : {
2269 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Aux_Taut_Prev && pINChI_Aux_Taut_Prev->nNumberOfAtoms)
# # ]
2270 : : {
2271 : 0 : if (bHasEquString( pINChI_Aux_Taut_Prev->nConstitEquNumbers, pINChI_Aux_Taut_Prev->nNumberOfAtoms ))
2272 : : {
2273 : : /* since pINChI_Aux_Prev does not exist, pINChI_Aux_Taut_Prev is non-tautomeric */
2274 : : /* and it has non-trivial equivalence info. This info has already been printed in the main section */
2275 : : /*
2276 : : MakeDelim( sIdenticalValues, strbuf, bOverflow);
2277 : : */
2278 : : }
2279 : : else
2280 : : {
2281 : : ; /* pINChI_Aux_Taut_Prev exists and has only trivial equivalence info */
2282 : : }
2283 : : }
2284 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
2285 : : else
2286 : : {
2287 : : int stop = 1; /* <BRKPT> */
2288 : : }
2289 : : #endif
2290 : : }
2291 : :
2292 : : }
2293 : :
2294 : 37 : pINChI_Aux_Prev = pINChI_Aux;
2295 : 37 : pINChI_Aux_Taut_Prev = pINChI_Aux_Taut;
2296 : 37 : mult = 0; /* we do not know whether the item is empty */
2297 : : }
2298 : : }
2299 : : }
2300 : :
2301 : 21 : return ( strbuf->nUsedLength - nUsedLength0 );
2302 : : }
2303 : :
2304 : :
2305 : : /****************************************************************************
2306 : : Produce tetrahedral stereo inversion substring of AuxInfo.
2307 : : ****************************************************************************/
2308 : 42 : int str_AuxInvSp3( INCHI_SORT *pINChISort,
2309 : : INCHI_SORT *pINChISort2,
2310 : : INCHI_IOS_STRING *strbuf,
2311 : : int *bOverflow,
2312 : : int bOutType,
2313 : : int TAUT_MODE,
2314 : : int num_components,
2315 : : int bSecondNonTautPass,
2316 : : int bOmitRepetitions,
2317 : : int bUseMulipliers )
2318 : : {
2319 : : int i, ii, ii2, nUsedLength0;
2320 : : INCHI_SORT *is, *is2, *is0, *is20;
2321 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
2322 : : INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
2323 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
2324 : : const char *pPrevEquStr, *pCurrEquStr;
2325 : : int multPrevEquStr;
2326 : : /***************
2327 : : inverted sp3
2328 : : ****************/
2329 : 42 : pINChI_Taut = NULL;
2330 : 42 : pINChI_Prev = NULL;
2331 : 42 : pINChI_Taut_Prev = NULL;
2332 : 42 : mult = 0;
2333 : 42 : bNext = 0;
2334 : 42 : is = NULL;
2335 : 42 : is2 = NULL;
2336 : 42 : is0 = pINChISort;
2337 [ - + ]: 42 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
2338 : : /* djb-rwth: removing redundant code */
2339 : 42 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
2340 : 42 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
2341 : 42 : multPrevEquStr = 0;
2342 : 42 : nUsedLength0 = strbuf->nUsedLength;
2343 : :
2344 : : /* For each connected component... */
2345 [ + + ]: 136 : for (i = 0; i <= num_components; i++)
2346 : : {
2347 : :
2348 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2349 [ + + - + : 94 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
2350 : : /*================ compare sp2 to previous =====================*/
2351 [ - + ]: 94 : if (bSecondNonTautPass)
2352 : : {
2353 : : /* component that was output on the 1st pass */
2354 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
2355 : : }
2356 : 94 : eq2taut = 0;
2357 : : /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
2358 [ - + - - ]: 94 : if (bSecondNonTautPass && bOmitRepetitions)
2359 : : {
2360 : : /* compare non-tautomeric inverted to:
2361 : : * a) tautomeric inverted
2362 : : * b) Inverted(tautomeric)
2363 : : * c) Inverted(non-tautomeric)
2364 : : */
2365 : : /* a) compare non-tautomeric inverted to tautomeric inverted */
2366 [ # # ]: 0 : if (!eq2taut)
2367 : : {
2368 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
2369 : : /* non-taut inverted */ /* taut invertedc */
2370 [ # # # # : 0 : ( Stereo = pINChI->Stereo ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
2371 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
2372 : : /* stereo-inv non-taut = taut (stereo-inv) */
2373 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitNONTAUT ) : 0;
2374 : : }
2375 : : /* b) compare non-tautomeric inverted to Inverted(tautomeric stereo) */
2376 [ # # ]: 0 : if (!eq2taut)
2377 : : {
2378 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
2379 [ # # # # : 0 : ( Stereo = pINChI->Stereo ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
2380 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3, 0 );
2381 : : /* stereo-inv non-taut = Inv(taut stereo) */
2382 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitNONTAUT | iiEq2INV ) : 0;
2383 : : }
2384 : : /* c) compare non-tautomeric inverted to Inverted(non-tautomeric stereo) */
2385 [ # # ]: 0 : if (!eq2taut)
2386 : : {
2387 : 0 : eq2taut = pINChI &&
2388 [ # # # # : 0 : ( Stereo = pINChI->Stereo ) &&
# # ]
2389 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo, EQL_SP3, 0 );
2390 : : /* stereo-inv non-taut = Inv(non-taut stereo) */
2391 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitNONTAUT | iiEq2INV | iiEq2NONTAUT ) : 0;
2392 : : }
2393 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
2394 : : if (!eq2taut && pINChI && pINChI_Taut &&
2395 : : !( ( Stereo = pINChI->Stereo ) && Eql_INChI_Stereo( Stereo, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ) ))
2396 : : {
2397 : : if (( Stereo_Taut = pINChI_Taut->Stereo ) &&
2398 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3, NULL, EQL_EXISTS, 0 ))
2399 : : {
2400 : :
2401 : : eq2taut = iiEmpty; /* the current is empty while the preceding (taut) is not */
2402 : : }
2403 : : }
2404 : : #endif
2405 : : }
2406 : : else
2407 : : /*========= if not bSecondNonTautPass then compare inv taut stereo to various taut stereo ========*/
2408 [ + - + - ]: 94 : if (!bSecondNonTautPass && bOmitRepetitions)
2409 : : {
2410 : : /* compare tautomeric inverted to Invetred(tautomeric) */
2411 [ + - ]: 94 : if (!eq2taut)
2412 : : {
2413 : 146 : eq2taut = pINChI &&
2414 [ + + + - : 146 : ( Stereo = pINChI->Stereo ) &&
+ + ]
2415 : 52 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo, EQL_SP3, 0 );
2416 : : /* stereo isotopic taut = taut (stereo) */
2417 [ + + ]: 94 : eq2taut = eq2taut ? ( iiSTEREO_INV | iiEq2INV ) : 0;
2418 : : }
2419 : : }
2420 [ + + ]: 94 : if (eq2taut)
2421 : : {
2422 : : /* we may be here only in case of the current layer found equal in another layer the same component */
2423 [ + + + - ]: 38 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
2424 : : {
2425 : : /* previous component exists; output it before output the current component */
2426 [ + + ]: 4 : if (bNext++)
2427 : : {
2428 : 1 : MakeDelim( sCompDelim, strbuf, bOverflow );
2429 : : }
2430 [ + - + - ]: 4 : if (( Stereo_Prev = pINChI_Prev->Stereo ) && Stereo_Prev->nNumberOfStereoCenters > 0)
2431 : : {
2432 : 4 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
2433 : :
2434 : 4 : MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parityInv,
2435 : : 0, Stereo_Prev->nNumberOfStereoCenters,
2436 : : strbuf, TAUT_MODE, bOverflow );
2437 : : }
2438 : : }
2439 : : else
2440 [ - + - - ]: 34 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
2441 : : {
2442 : : /* previous non-taut component exists only in taut list */
2443 [ # # ]: 0 : if (bNext++)
2444 : : {
2445 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2446 : : }
2447 : : /* do not output stereo of non-tautomeric in non-taut layer: it has been output in the main layer */
2448 : : }
2449 : : /* we have found another (previously printed) layer of the current component equal to this layer */
2450 : : /* output this (current) equivalence mark = EquString(eq2taut) */
2451 : 38 : pCurrEquStr = EquString( eq2taut );
2452 [ + + + - ]: 38 : if (multPrevEquStr && pPrevEquStr)
2453 : : {
2454 [ + - + - ]: 3 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
2455 : : {
2456 : 3 : multPrevEquStr++;
2457 : : }
2458 : : else
2459 : : {
2460 : : /* new EqStr is different; output it */
2461 [ # # ]: 0 : if (bNext++)
2462 : : {
2463 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2464 : : }
2465 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2466 : 0 : pPrevEquStr = pCurrEquStr;
2467 : 0 : multPrevEquStr = 1;
2468 : : }
2469 : : }
2470 : : else
2471 : : {
2472 : 35 : pPrevEquStr = pCurrEquStr;
2473 : 35 : multPrevEquStr = 1;
2474 : : }
2475 : 38 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
2476 : 38 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
2477 : 38 : mult = 0;
2478 : 38 : eq2tautPrev = 1; /* pINChI_Prev and pINChI_Taut_Prev have already been output */
2479 : : }
2480 : : else
2481 [ + + ]: 56 : if (eq2tautPrev)
2482 : : {
2483 : : /* at this point pINChI_Prev does not exist; however, pINChI */
2484 : : /*might have been discovered and it is different from pINChI_Taut */
2485 [ + + + - ]: 46 : if (multPrevEquStr && pPrevEquStr)
2486 : : {
2487 : : /* new EqStr is different; output it */
2488 [ + + ]: 35 : if (bNext++)
2489 : : {
2490 : 4 : MakeDelim( sCompDelim, strbuf, bOverflow );
2491 : : }
2492 : 35 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2493 : 35 : pPrevEquStr = NULL;
2494 : 35 : multPrevEquStr = 0;
2495 : : }
2496 : 46 : eq2tautPrev = 0;
2497 : 46 : pINChI_Prev = pINChI;
2498 : 46 : pINChI_Taut_Prev = pINChI_Taut;
2499 : 46 : mult = 0;
2500 : : }
2501 : : else
2502 : : {
2503 : : /* current layer is different from previously printed layers of the current component */
2504 : : /* compare the current layer to this layer of the previous component: */
2505 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
2506 : : /*================ compare iso sp3 to previous =====================*/
2507 [ - + ]: 10 : eq2prev = bUseMulipliers &&
2508 [ # # ]: 0 : pINChI && pINChI_Prev &&
2509 : : /* do both have stereo? */
2510 [ + - - - : 20 : ( Stereo = pINChI->Stereo ) && ( Stereo_Prev = pINChI_Prev->Stereo ) &&
- - - - ]
2511 : : /* is their inverted stereo same? */
2512 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Prev, EQL_SP3_INV, 0 );
2513 [ - + ]: 10 : if (eq2prev)
2514 : : {
2515 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
2516 : 0 : continue;
2517 : : }
2518 : : else
2519 : : {
2520 [ + + ]: 10 : if (bNext++)
2521 : : {
2522 : 2 : MakeDelim( sCompDelim, strbuf, bOverflow );
2523 : : }
2524 [ + - + - ]: 10 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
2525 : : {
2526 [ + - ]: 10 : if (( Stereo_Prev = pINChI_Prev->Stereo ) &&
2527 [ + + + - ]: 10 : Stereo_Prev->nNumberOfStereoCenters > 0 && Stereo_Prev->nCompInv2Abs)
2528 : : {
2529 : 9 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
2530 : :
2531 : 9 : MakeStereoString( Stereo_Prev->nNumberInv, NULL, Stereo_Prev->t_parityInv,
2532 : : 0, Stereo_Prev->nNumberOfStereoCenters,
2533 : : strbuf, TAUT_MODE, bOverflow );
2534 : : }
2535 : : /* else sp3 info is not present in pINChI_Prev */
2536 : : }
2537 : : else
2538 : : /* do not print pINChI_Prev because it either do not exist of have already been printed */
2539 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
2540 : : {
2541 [ # # ]: 0 : if (( Stereo_Taut_Prev = pINChI_Taut_Prev->Stereo ) &&
2542 [ # # ]: 0 : Stereo_Taut_Prev->nNumberOfStereoCenters > 0 && Stereo_Taut_Prev->nCompInv2Abs)
2543 : : {
2544 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
2545 : : /* and it has non-trivial inv sp3 info. It has already been printed in the main section */
2546 : : /*
2547 : : MakeDelim( sIdenticalValues, strbuf, bOverflow);
2548 : : */
2549 : : ;/* pINChI_Taut_Prev sp3 info was output in the main stereo section */
2550 : : }
2551 : : else
2552 : : {
2553 : : ; /* pINChI_Taut_Prev exists and has not sp3 info */
2554 : : }
2555 : : }
2556 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
2557 : : else
2558 : : {
2559 : : int stop = 1; /* <BRKPT> */
2560 : : }
2561 : : #endif
2562 : : }
2563 : 10 : pINChI_Prev = pINChI;
2564 : 10 : mult = 0; /* we do not know whether the item is empty */
2565 : : }
2566 : : }
2567 : :
2568 : 42 : return ( strbuf->nUsedLength - nUsedLength0 );
2569 : : }
2570 : :
2571 : :
2572 : : /****************************************************************************
2573 : : Produce tetrahedral stereo inversion numbering substring of AuxInfo
2574 : : /iN: in Main and/or Isotopic and/or FixedH-Iso parts,
2575 : : in both normal and reconnected layers
2576 : : ****************************************************************************/
2577 : 0 : int str_AuxInvSp3Numb( CANON_GLOBALS *pCG,
2578 : : INCHI_SORT *pINChISort,
2579 : : INCHI_SORT *pINChISort2,
2580 : : INCHI_IOS_STRING *strbuf,
2581 : : int *bOverflow,
2582 : : int bOutType,
2583 : : int TAUT_MODE,
2584 : : int num_components,
2585 : : int bSecondNonTautPass,
2586 : : int bOmitRepetitions )
2587 : : {
2588 : : int i, ii, ii2, nUsedLength0;
2589 : : INCHI_SORT *is, *is0 /*, *is2*/;
2590 : : INChI *pINChI, *pINChI_Taut;
2591 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Taut; /* djb-rwth: removing redundant variables */
2592 : : INChI_Stereo *Stereo, *Stereo_Taut;
2593 : : int eq2taut, bNext;
2594 : : const char *pPrevEquStr, *pCurrEquStr;
2595 : : int multPrevEquStr;
2596 : : /**************************************************
2597 : : * specificity of numbering: there is no previous *
2598 : : * component because no repetition is possible *
2599 : : **************************************************/
2600 : 0 : pINChI = NULL;
2601 : 0 : pINChI_Taut = NULL;
2602 : 0 : pINChI_Aux = NULL;
2603 : 0 : pINChI_Aux_Taut = NULL;
2604 : : /* djb-rwth: removing redundant code */
2605 : 0 : bNext = 0;
2606 : 0 : is = NULL;
2607 : 0 : is0 = pINChISort;
2608 : : /*is2 = bSecondNonTautPass? pINChISort2 : NULL;*/
2609 : : /* djb-rwth: removing redundant code */
2610 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
2611 : 0 : multPrevEquStr = 0;
2612 : 0 : nUsedLength0 = strbuf->nUsedLength;
2613 : :
2614 : : /* For each connected component... */
2615 [ # # ]: 0 : for (i = 0; i < num_components; i++)
2616 : : {
2617 : :
2618 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2619 : 0 : is = is0 + i;
2620 [ # # # # : 0 : pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
2621 [ # # ]: 0 : pINChI_Aux = pINChI ? is->pINChI_Aux[ii] : NULL;
2622 : : /*================ to compare to previously printed =====================*/
2623 [ # # ]: 0 : if (bSecondNonTautPass)
2624 : : {
2625 : : /* component that was printed on the 1st pass */
2626 [ # # # # : 0 : pINChI_Taut = ( 0 <= ( ii2 = GET_II( OUT_T1, is ) ) ) ? is->pINChI[ii2] : NULL;
# # # # #
# ]
2627 [ # # ]: 0 : pINChI_Aux_Taut = pINChI_Taut ? is->pINChI_Aux[ii2] : NULL;
2628 : : }
2629 : :
2630 : 0 : eq2taut = 0;
2631 : : /*========= if bSecondNonTautPass then compare inv non-taut stereo to other stereo ========*/
2632 [ # # # # : 0 : if (bSecondNonTautPass && bOmitRepetitions &&
# # ]
2633 [ # # # # ]: 0 : pINChI && ( Stereo = pINChI->Stereo ) && Stereo->nCompInv2Abs)
2634 : : {
2635 : : /* compare non-tautomeric inverted stereo numbering to:
2636 : : * a) tautomeric numbering
2637 : : * b) non-tautomeric numbering
2638 : : * c) tautomeric inverted stereo numbering
2639 : : */
2640 : : /* a) compare non-tautomeric inverted stereo numbering to tautomeric numbering */
2641 [ # # ]: 0 : if (!eq2taut)
2642 : : {
2643 [ # # # # ]: 0 : eq2taut = pINChI_Taut &&
2644 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV, pINChI_Aux_Taut, EQL_NUM );
2645 : : /* stereo-inv numbering non-taut = taut numbering */
2646 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iiNUMB | iitNONTAUT ) : 0;
2647 : : }
2648 : : /* b) compare non-tautomeric inverted stereo numbering to non-tautomeric numbering */
2649 [ # # ]: 0 : if (!eq2taut)
2650 : : {
2651 : : eq2taut =
2652 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV, pINChI_Aux, EQL_NUM );
2653 : : /* stereo-inv numb. non-taut = non-taut numbering */
2654 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iiNUMB | iitNONTAUT | iiEq2NONTAUT ) : 0;
2655 : : }
2656 : : /* c) compare non-tautomeric inverted stereo numbering to tautomeric inverted stereo numbering */
2657 [ # # ]: 0 : if (!eq2taut)
2658 : : {
2659 : 0 : eq2taut = pINChI_Taut &&
2660 [ # # # # : 0 : ( Stereo_Taut = pINChI_Taut->Stereo ) && Stereo_Taut->nCompInv2Abs &&
# # # # ]
2661 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV, pINChI_Aux_Taut, EQL_NUM_INV );
2662 : : /* stereo-inv numb. non-taut = taut inv stereo numbering */
2663 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iiNUMB | iitNONTAUT | iiEq2INV ) : 0;
2664 : : }
2665 : : }
2666 : : else
2667 : : {
2668 : : /*========= if not bSecondNonTautPass then compare inv taut stereo numb to taut numb ========*/
2669 [ # # # # : 0 : if (!bSecondNonTautPass && bOmitRepetitions &&
# # ]
2670 [ # # # # ]: 0 : pINChI && ( Stereo = pINChI->Stereo ) && Stereo->nCompInv2Abs)
2671 : : {
2672 : : /* compare tautomeric inverted stereo numbering to tautomeric numbering */
2673 [ # # ]: 0 : if (!eq2taut)
2674 : : {
2675 : : eq2taut =
2676 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV, pINChI_Aux, EQL_NUM );
2677 : : /* stereo-inv numbering (taut) = taut numbering */
2678 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iiNUMB ) : 0;
2679 : : }
2680 : : }
2681 : : }
2682 [ # # ]: 0 : if (eq2taut)
2683 : : {
2684 : : /* we have found another (previously printed) layer of the current component equal to this layer */
2685 : : /* output this (current) equivalence mark = EquString(eq2taut) */
2686 : 0 : pCurrEquStr = EquString( eq2taut );
2687 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2688 : : {
2689 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
2690 : : {
2691 : 0 : multPrevEquStr++;
2692 : : }
2693 : : else
2694 : : {
2695 : : /* new EqStr is different; output it */
2696 [ # # ]: 0 : if (bNext++)
2697 : : {
2698 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2699 : : }
2700 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2701 : 0 : pPrevEquStr = pCurrEquStr;
2702 : 0 : multPrevEquStr = 1;
2703 : : }
2704 : : }
2705 : : else
2706 : : {
2707 : 0 : pPrevEquStr = pCurrEquStr;
2708 : 0 : multPrevEquStr = 1;
2709 : : }
2710 : : }
2711 : : else
2712 : : {
2713 : : /* current layer is different from previously printed layers of the current component */
2714 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2715 : : {
2716 : : /* new EqStr is different; output it */
2717 [ # # ]: 0 : if (bNext++)
2718 : : {
2719 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2720 : : }
2721 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2722 : 0 : pPrevEquStr = NULL;
2723 : 0 : multPrevEquStr = 0;
2724 : : }
2725 [ # # ]: 0 : if (bNext++)
2726 : : {
2727 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2728 : : }
2729 [ # # # # : 0 : if (pINChI && pINChI_Aux && pINChI_Aux->nNumberOfAtoms &&
# # ]
2730 [ # # # # ]: 0 : ( Stereo = pINChI->Stereo ) && Stereo->nNumberOfStereoCenters &&
2731 [ # # # # ]: 0 : Stereo->nCompInv2Abs && pINChI_Aux->nOrigAtNosInCanonOrdInv)
2732 : : {
2733 : 0 : MakeCtString( pCG, pINChI_Aux->nOrigAtNosInCanonOrdInv,
2734 : : pINChI_Aux->nNumberOfAtoms, 0, NULL, 0,
2735 : : strbuf, TAUT_MODE, bOverflow );
2736 : : }
2737 : : /* else inv stereo info is not present in pINChI */
2738 : : }
2739 : : }
2740 : :
2741 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2742 : : {
2743 : : /* the new EqStr of the last item has not been printed; output it now */
2744 [ # # ]: 0 : if (bNext++)
2745 : : {
2746 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2747 : : }
2748 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2749 : 0 : pPrevEquStr = NULL;
2750 : : /* djb-rwth: removing redundant code */
2751 : : }
2752 : :
2753 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
2754 : : }
2755 : :
2756 : :
2757 : : /****************************************************************************
2758 : : Produce isotopic numbering substring of AuxInfo
2759 : : /I: in Isotopic and/or FixedH-Iso parts,
2760 : : in both normal and reconnected layers
2761 : : ****************************************************************************/
2762 : 0 : int str_AuxIsoNumb( CANON_GLOBALS *pCG,
2763 : : INCHI_SORT *pINChISort,
2764 : : INCHI_SORT *pINChISort2,
2765 : : INCHI_IOS_STRING *strbuf,
2766 : : int *bOverflow,
2767 : : int bOutType,
2768 : : int TAUT_MODE,
2769 : : int num_components,
2770 : : int bSecondNonTautPass,
2771 : : int bOmitRepetitions )
2772 : : {
2773 : : int i, ii, ii2, nUsedLength0;
2774 : : INCHI_SORT *is, *is0 /*, *is2*/;
2775 : : /* djb-rwth: removing redundant variables */
2776 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Taut; /* djb-rwth: removing redundant variables */
2777 : : int eq2taut, bNext;
2778 : : const char *pPrevEquStr, *pCurrEquStr;
2779 : : int multPrevEquStr;
2780 : : /**************************************************
2781 : : * specificity of numbering: there is no previous *
2782 : : * component because no repetition is possible *
2783 : : **************************************************/
2784 : : /* djb-rwth: removing redundant code */
2785 : 0 : pINChI_Aux = NULL;
2786 : 0 : pINChI_Aux_Taut = NULL;
2787 : : /* djb-rwth: removing redundant code */
2788 : 0 : bNext = 0;
2789 : 0 : is = NULL;
2790 : 0 : is0 = pINChISort;
2791 : : /*is2 = bSecondNonTautPass? pINChISort2 : NULL;*/
2792 : : /* djb-rwth: removing redundant code */
2793 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
2794 : 0 : multPrevEquStr = 0;
2795 : 0 : nUsedLength0 = strbuf->nUsedLength;
2796 : :
2797 : : /* For each connected component... */
2798 [ # # ]: 0 : for (i = 0; i < num_components; i++)
2799 : : {
2800 : :
2801 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2802 : 0 : is = is0 + i;
2803 [ # # # # : 0 : pINChI_Aux = ( i < num_components && 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI_Aux[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
2804 : : /*================ to compare to previously printed =====================*/
2805 [ # # ]: 0 : if (bSecondNonTautPass)
2806 : : {
2807 [ # # # # : 0 : pINChI_Aux_Taut = ( 0 <= ( ii2 = GET_II( OUT_T1, is ) ) ) ? is->pINChI_Aux[ii2] : NULL;
# # # # #
# ]
2808 : : }
2809 : 0 : eq2taut = 0;
2810 : : /*========= if bSecondNonTautPass then compare iso non-taut numb to other numb ========*/
2811 [ # # # # : 0 : if (bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic)
# # # # ]
2812 : : {
2813 : : /* compare non-tautomeric isotopic numbering to:
2814 : : * a) tautomeric numbering
2815 : : * b) non-tautomeric numbering
2816 : : * c) tautomeric isotopic numbering
2817 : : */
2818 : : /* a) compare non-tautomeric isotopic numbering to tautomeric numbering */
2819 [ # # ]: 0 : if (!eq2taut)
2820 : : {
2821 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM );
2822 : : /* numbering non-taut isotopic = taut numbering */
2823 [ # # ]: 0 : eq2taut = eq2taut ? ( iiNUMB | iitNONTAUT | iitISO ) : 0;
2824 : : }
2825 : : /* b) compare non-tautomeric isotopic numbering to non-tautomeric numbering */
2826 [ # # ]: 0 : if (!eq2taut)
2827 : : {
2828 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux, EQL_NUM );
2829 : : /* numbering non-taut isotopic = non-taut numbering */
2830 [ # # ]: 0 : eq2taut = eq2taut ? ( iiNUMB | iitNONTAUT | iitISO | iiEq2NONTAUT ) : 0;
2831 : : }
2832 : : /* c) compare non-tautomeric isotopic numbering to tautomeric isotopic numbering */
2833 [ # # ]: 0 : if (!eq2taut)
2834 : : {
2835 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM_ISO );
2836 : : /* numbering non-taut isotopic = taut isotopic numbering */
2837 [ # # ]: 0 : eq2taut = eq2taut ? ( iiNUMB | iitNONTAUT | iitISO | iiEq2ISO ) : 0;
2838 : : }
2839 : : }
2840 : : else
2841 : : {
2842 : : /* 2011-10-28
2843 : : Fix bug in src:cano mapping of atoms printed to AuxInfo
2844 : : Reported by Sandor Mark on 2011-10-25 in inchi-discuss
2845 : : See http://sourceforge.net/p/inchi/mailman/message/28292914/ also
2846 : : */
2847 : : #define AUX_ISO_NUMB_BUG_FIX
2848 : : #ifdef AUX_ISO_NUMB_BUG_FIX
2849 : : /* Bug-fixed version */
2850 : : /*========= if not bSecondNonTautPass then compare isotopic taut numbering to taut numbering ========*/
2851 [ # # # # : 0 : if (!bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic)
# # # # ]
2852 : : {
2853 : : /* compare tautomeric isotopic numbering to tautomeric non-isotopic numbering */
2854 [ # # ]: 0 : if (!eq2taut)
2855 : : {
2856 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux, EQL_NUM );
2857 : : /* numbering isotopic (taut) = taut numbering */
2858 [ # # ]: 0 : eq2taut = eq2taut ? ( iiNUMB | iitISO ) : 0;
2859 : : }
2860 : : }
2861 : : #else
2862 : : /* Original (buggy) version */
2863 : :
2864 : : /*========= if not bSecondNonTautPass then compare inv taut stereo numb to taut numb ========*/
2865 : : if (!bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic)
2866 : : {
2867 : : /* compare tautomeric isotopic numbering to tautomeric non-isotopic numbering */
2868 : : if (!eq2taut)
2869 : : {
2870 : : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux, EQL_NUM_ISO );
2871 : : /* stereo-inv numbering (taut) = taut numbering */
2872 : : eq2taut = eq2taut ? ( iiSTEREO_INV | iiNUMB ) : 0;
2873 : : }
2874 : : }
2875 : : #endif
2876 : : }
2877 : :
2878 [ # # ]: 0 : if (eq2taut)
2879 : : {
2880 : : /* we have found another (previously printed) layer of the current component equal to this layer */
2881 : : /* output this (current) equivalence mark = EquString(eq2taut) */
2882 : 0 : pCurrEquStr = EquString( eq2taut );
2883 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2884 : : {
2885 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
2886 : : {
2887 : 0 : multPrevEquStr++;
2888 : : }
2889 : : else
2890 : : {
2891 : : /* new EqStr is different; output it */
2892 [ # # ]: 0 : if (bNext++)
2893 : : {
2894 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2895 : : }
2896 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2897 : 0 : pPrevEquStr = pCurrEquStr;
2898 : 0 : multPrevEquStr = 1;
2899 : : }
2900 : : }
2901 : : else
2902 : : {
2903 : 0 : pPrevEquStr = pCurrEquStr;
2904 : 0 : multPrevEquStr = 1;
2905 : : }
2906 : : }
2907 : : else
2908 : : {
2909 : : /* current layer is different from previously printed layers of the current component */
2910 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2911 : : {
2912 : : /* new EqStr is different; output it */
2913 [ # # ]: 0 : if (bNext++)
2914 : : {
2915 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2916 : : }
2917 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2918 : 0 : pPrevEquStr = NULL;
2919 : 0 : multPrevEquStr = 0;
2920 : : }
2921 [ # # ]: 0 : if (bNext++)
2922 : : {
2923 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2924 : : }
2925 [ # # # # : 0 : if (pINChI_Aux && pINChI_Aux->nNumberOfAtoms && pINChI_Aux->bIsIsotopic &&
# # ]
2926 [ # # ]: 0 : pINChI_Aux->nIsotopicOrigAtNosInCanonOrd)
2927 : : {
2928 : 0 : MakeCtString( pCG, pINChI_Aux->nIsotopicOrigAtNosInCanonOrd,
2929 : : pINChI_Aux->nNumberOfAtoms,
2930 : : 0, NULL, 0, strbuf, TAUT_MODE, bOverflow );
2931 : : }
2932 : : /* else isotopic numbering is not present in pINChI */
2933 : : }
2934 : : }
2935 : :
2936 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2937 : : {
2938 : : /* the new EqStr of the last item has not been printed; output it now */
2939 [ # # ]: 0 : if (bNext++)
2940 : : {
2941 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2942 : : }
2943 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2944 : 0 : pPrevEquStr = NULL;
2945 : : /* djb-rwth: removing redundant code */
2946 : : }
2947 : :
2948 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
2949 : : }
2950 : :
2951 : :
2952 : : /****************************************************************************
2953 : : Produce isotopic equivalence substring of AuxInfo.
2954 : : ****************************************************************************/
2955 : 0 : int str_AuxIsoEqu( INCHI_SORT *pINChISort,
2956 : : INCHI_SORT *pINChISort2,
2957 : : INCHI_IOS_STRING *strbuf,
2958 : : int *bOverflow,
2959 : : int bOutType,
2960 : : int TAUT_MODE,
2961 : : int num_components,
2962 : : int bSecondNonTautPass,
2963 : : int bOmitRepetitions,
2964 : : int bUseMulipliers )
2965 : : {
2966 : : int i, ii, ii2, nUsedLength0;
2967 : : INCHI_SORT *is, *is2, *is0, *is20;
2968 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev, *pINChI_Aux_Taut, *pINChI_Aux_Taut_Prev;
2969 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
2970 : : const char *pPrevEquStr, *pCurrEquStr;
2971 : : int multPrevEquStr;
2972 : 0 : pINChI_Aux = NULL;
2973 : 0 : pINChI_Aux_Prev = NULL;
2974 : 0 : pINChI_Aux_Taut = NULL;
2975 : 0 : pINChI_Aux_Taut_Prev = NULL;
2976 : 0 : mult = 0;
2977 : 0 : bNext = 0;
2978 : 0 : is = NULL;
2979 : 0 : is2 = NULL;
2980 : 0 : is0 = pINChISort;
2981 [ # # ]: 0 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
2982 : : /* djb-rwth: removing redundant code */
2983 : 0 : eq2tautPrev = 1; /* pINChI_Aux_Prev (previous pINChI_Aux) does not exist */
2984 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
2985 : 0 : multPrevEquStr = 0;
2986 : 0 : nUsedLength0 = strbuf->nUsedLength;
2987 : :
2988 : : /* For each connected component... */
2989 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
2990 : : {
2991 : :
2992 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2993 [ # # # # : 0 : pINChI_Aux = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI_Aux[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
2994 [ # # ]: 0 : if (bSecondNonTautPass)
2995 : : {
2996 : : /* component that was output on the 1st pass */
2997 [ # # # # : 0 : pINChI_Aux_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI_Aux[ii2] : NULL;
# # # # #
# # # ]
2998 : : }
2999 : : /*================ compare iso non-taut equivalence info to non-iso taut ========*/
3000 : 0 : eq2taut = 0;
3001 [ # # # # : 0 : if (bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic)
# # # # ]
3002 : : {
3003 : : /**************************************************
3004 : : * compare isotopic non-tautomeric equivalence to:
3005 : : * a) tautomeric
3006 : : * b) non-tautomeric
3007 : : * c) isotopic tautomeric
3008 : : */
3009 [ # # ]: 0 : if (!eq2taut)
3010 : : {
3011 : : /* compare isotopic non-tautomeric equivalence to tautomeric */
3012 : 0 : eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux_Taut, EQL_EQU );
3013 : : /* equ non-taut isotopic = tautomeric*/
3014 [ # # ]: 0 : eq2taut = eq2taut ? ( iiEQU | iitNONTAUT | iitISO ) : 0;
3015 : : }
3016 [ # # ]: 0 : if (!eq2taut)
3017 : : {
3018 : : /* compare isotopic non-tautomeric equivalence to non-tautomeric */
3019 : 0 : eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux, EQL_EQU );
3020 : : /* equ non-taut isotopic = non-tautomeric*/
3021 [ # # ]: 0 : eq2taut = eq2taut ? ( iiEQU | iitNONTAUT | iitISO | iiEq2NONTAUT ) : 0;
3022 : : }
3023 [ # # ]: 0 : if (!eq2taut)
3024 : : {
3025 : : /* compare isotopic non-tautomeric equivalence to isotopic tautomeric */
3026 : 0 : eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux_Taut, EQL_EQU_ISO );
3027 : : /* equ non-taut isotopic = isotopic tautomeric*/
3028 [ # # ]: 0 : eq2taut = eq2taut ? ( iiEQU | iitNONTAUT | iitISO | iiEq2ISO ) : 0;
3029 : : }
3030 : : }
3031 : : else
3032 : : {
3033 [ # # # # : 0 : if (!bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic)
# # # # ]
3034 : : {
3035 : : /**************************************************
3036 : : * compare isotopic tautomeric equivalence to:
3037 : : * a) non-isotopic tautomeric
3038 : : */
3039 [ # # ]: 0 : if (!eq2taut)
3040 : : {
3041 : : /* compare isotopic tautomeric equivalence to tautomeric */
3042 : 0 : eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux, EQL_EQU );
3043 : : /* equ taut-isotopic = tautomeric*/
3044 [ # # ]: 0 : eq2taut = eq2taut ? ( iiEQU | iitISO ) : 0;
3045 : : }
3046 : : }
3047 : : }
3048 [ # # ]: 0 : if (eq2taut)
3049 : : {
3050 : : /* we may be here only in case of the second (non-taut) pass */
3051 : : /* current non-taut equivalence has been found to be same as tautomeric */
3052 [ # # # # ]: 0 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
3053 : : {
3054 : : /* previous component exists */
3055 [ # # ]: 0 : if (bNext++)
3056 : : {
3057 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3058 : : }
3059 [ # # ]: 0 : if (bHasEquString( pINChI_Aux_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Prev->nNumberOfAtoms ))
3060 : : {
3061 : : /* output previous component(s) equivalence since it was found to be non-trivial */
3062 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
3063 : 0 : MakeEquString( pINChI_Aux_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Prev->nNumberOfAtoms, 0,
3064 : : strbuf, TAUT_MODE, bOverflow );
3065 : : }
3066 : : else
3067 : : {
3068 : : ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
3069 : : }
3070 : : }
3071 : : else
3072 : : {
3073 [ # # # # ]: 0 : if (pINChI_Aux_Taut_Prev && pINChI_Aux_Taut_Prev->nNumberOfAtoms)
3074 : : {
3075 : : /* previous non-taut component exists only in taut list */
3076 [ # # ]: 0 : if (bNext++)
3077 : : {
3078 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3079 : : }
3080 : : }
3081 : : }
3082 : : /* we have found pINChI_Aux->pINChI_Aux->nConstitEquIsotopicNumbers same as in pINChI_Aux_Taut */
3083 : : /* output this (current) equivalence as '*', that is, same as tautomeric */
3084 : : /* that was printed on the 1st pass. */
3085 : 0 : pCurrEquStr = EquString( eq2taut );
3086 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3087 : : {
3088 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
3089 : : {
3090 : 0 : multPrevEquStr++;
3091 : : }
3092 : : else
3093 : : {
3094 : : /* new EqStr is different; output it */
3095 [ # # ]: 0 : if (bNext++)
3096 : : {
3097 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3098 : : }
3099 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3100 : 0 : pPrevEquStr = pCurrEquStr;
3101 : 0 : multPrevEquStr = 1;
3102 : : }
3103 : : }
3104 : : else
3105 : : {
3106 : 0 : pPrevEquStr = pCurrEquStr;
3107 : 0 : multPrevEquStr = 1;
3108 : : }
3109 : 0 : pINChI_Aux_Prev = NULL; /* pINChI_Aux_Prev does not exist since */
3110 : 0 : pINChI_Aux_Taut_Prev = NULL; /* pINChI_Aux has just been printed */
3111 : 0 : mult = 0;
3112 : 0 : eq2tautPrev = 1;
3113 : : }
3114 : : else
3115 : : {
3116 [ # # ]: 0 : if (eq2tautPrev)
3117 : : {
3118 : : /* at this point pINChI_Aux_Prev does not exist; however, pINChI_Aux */
3119 : : /*might have been discovered and it is different from pINChI_Aux_Taut */
3120 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3121 : : {
3122 : : /* new EqStr is different; output it */
3123 [ # # ]: 0 : if (bNext++)
3124 : : {
3125 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3126 : : }
3127 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3128 : 0 : pPrevEquStr = NULL;
3129 : 0 : multPrevEquStr = 0;
3130 : : }
3131 : 0 : eq2tautPrev = 0;
3132 : 0 : pINChI_Aux_Prev = pINChI_Aux;
3133 : 0 : pINChI_Aux_Taut_Prev = pINChI_Aux_Taut;
3134 : 0 : mult = 0;
3135 : : }
3136 : : else
3137 : : {
3138 : : /* check whether pINChI_Aux and pINChI_Aux_Prev have identical non-trivial equivalence info */
3139 [ # # # # ]: 0 : eq2prev = bUseMulipliers && Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux_Prev, EQL_EQU_ISO );
3140 [ # # ]: 0 : if (eq2prev)
3141 : : {
3142 : : /* eq. info is same and non-trivial */
3143 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
3144 : 0 : continue;
3145 : : }
3146 : : else
3147 : : {
3148 : : /* pINChI_Aux eq. info is either different or trivial. Output pINChI_Aux_Prev anyway */
3149 [ # # ]: 0 : if (bNext++)
3150 : : {
3151 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3152 : : }
3153 [ # # # # ]: 0 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
3154 : : {
3155 [ # # ]: 0 : if (bHasEquString( pINChI_Aux_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Prev->nNumberOfAtoms ))
3156 : : {
3157 : : /* pINChI_Aux_Prev exists and has equivalence info */
3158 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
3159 : 0 : MakeEquString( pINChI_Aux_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Prev->nNumberOfAtoms, 0,
3160 : : strbuf, TAUT_MODE, bOverflow );
3161 : : }
3162 : : else
3163 : : {
3164 : : ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
3165 : : }
3166 : : }
3167 : : else
3168 : : {
3169 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Aux_Taut_Prev && pINChI_Aux_Taut_Prev->nNumberOfAtoms)
# # ]
3170 : : {
3171 : 0 : if (bHasEquString( pINChI_Aux_Taut_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Taut_Prev->nNumberOfAtoms ))
3172 : : {
3173 : : /* since pINChI_Aux_Prev does not exist, pINChI_Aux_Taut_Prev is non-tautomeric */
3174 : : /* and it has non-trivial equivalence info. This info has already been printed in the main section */
3175 : : /*
3176 : : MakeDelim( sIdenticalValues, strbuf, bOverflow);
3177 : : */
3178 : : }
3179 : : else
3180 : : {
3181 : : ; /* pINChI_Aux_Taut_Prev exists and has only trivial equivalence info */
3182 : : }
3183 : : }
3184 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
3185 : : else
3186 : : {
3187 : : int stop = 1; /* <BRKPT> */
3188 : : }
3189 : : #endif
3190 : : }
3191 : : }
3192 : 0 : pINChI_Aux_Prev = pINChI_Aux;
3193 : 0 : pINChI_Aux_Taut_Prev = pINChI_Aux_Taut;
3194 : 0 : mult = 0; /* we do not know whether the item is empty */
3195 : : }
3196 : : }
3197 : : }
3198 : :
3199 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
3200 : : }
3201 : :
3202 : :
3203 : : /****************************************************************************
3204 : : Produce isotopic tetr stereo inversion substring of AuxInfo.
3205 : : ****************************************************************************/
3206 : 0 : int str_AuxInvIsoSp3( INCHI_SORT *pINChISort,
3207 : : INCHI_SORT *pINChISort2,
3208 : : INCHI_IOS_STRING *strbuf,
3209 : : int *bOverflow,
3210 : : int bOutType,
3211 : : int TAUT_MODE,
3212 : : int num_components,
3213 : : int bSecondNonTautPass,
3214 : : int bOmitRepetitions,
3215 : : int bUseMulipliers )
3216 : : {
3217 : : int i, ii, ii2, nUsedLength0;
3218 : : INCHI_SORT *is, *is2, *is0, *is20;
3219 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
3220 : : INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
3221 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
3222 : : const char *pPrevEquStr, *pCurrEquStr;
3223 : : int multPrevEquStr;
3224 : : /********************************
3225 : : inverted isotopic sp3
3226 : : *********************************/
3227 : 0 : pINChI_Taut = NULL;
3228 : 0 : pINChI_Prev = NULL;
3229 : 0 : pINChI_Taut_Prev = NULL;
3230 : 0 : mult = 0;
3231 : 0 : bNext = 0;
3232 : 0 : is = NULL;
3233 : 0 : is2 = NULL;
3234 : 0 : is0 = pINChISort;
3235 [ # # ]: 0 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
3236 : : /* djb-rwth: removing redundant code */
3237 : 0 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
3238 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
3239 : 0 : multPrevEquStr = 0;
3240 : 0 : nUsedLength0 = strbuf->nUsedLength;
3241 : :
3242 : : /* For each connected component... */
3243 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
3244 : : {
3245 : :
3246 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
3247 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
3248 : : /*================ compare sp2 to previous =====================*/
3249 [ # # ]: 0 : if (bSecondNonTautPass)
3250 : : {
3251 : : /* component that was output on the 1st pass */
3252 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
3253 : : }
3254 : 0 : eq2taut = 0;
3255 : : /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
3256 [ # # # # : 0 : if (bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI->nNumberOfIsotopicAtoms + pINChI->nNumberOfIsotopicTGroups > 0)
# # # # ]
3257 : : {
3258 : : /* compare non-tautomeric isotopic inverted to:
3259 : : * a) tautomeric inverted
3260 : : * b) *non-tautomeric inverted
3261 : : * c) *isotopic tautomeric inverted
3262 : : * d) Inverted(tautomeric)
3263 : : * e) *Inverted(tautomeric isotopic)
3264 : : * f) Inverted(non-tautomeric)
3265 : : * g) *Inverted(non-tautomeric isotopic)
3266 : : */
3267 : : /* a) compare non-tautomeric isotopic inverted to tautomeric inverted */
3268 [ # # ]: 0 : if (!eq2taut)
3269 : : {
3270 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
3271 : : /* non-taut inverted */ /* taut invertedc */
3272 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
3273 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
3274 : : /* stereo-inv isotopic non-taut = taut (stereo-inv) */
3275 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT ) : 0;
3276 : : }
3277 : : /* b) compare non-tautomeric isotopic inverted to non-tautomeric inverted */
3278 [ # # ]: 0 : if (!eq2taut)
3279 : : {
3280 : 0 : eq2taut = pINChI && /* it is non-taut non-iso stereo */
3281 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
3282 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
3283 : : /* stereo-inv isotopic non-taut = non-taut stereo-inv */
3284 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2NONTAUT ) : 0;
3285 : : }
3286 : : /* c) compare non-tautomeric isotopic inverted to isotopic tautomeric inverted */
3287 [ # # ]: 0 : if (!eq2taut)
3288 : : {
3289 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
3290 : : /* non-taut iso. inverted */ /* taut iso. inverted */
3291 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) &&
# # # # ]
3292 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
3293 : : /* stereo-inv isotopic non-taut = taut iso. stereo-inv */
3294 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2ISO ) : 0;
3295 : : }
3296 : : /* d) compare non-tautomeric inverted to Inverted(tautomeric stereo) */
3297 [ # # ]: 0 : if (!eq2taut)
3298 : : {
3299 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
3300 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
3301 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
3302 : : /* stereo-inv isotopic non-taut = Inv(non-iso taut stereo) */
3303 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2INV ) : 0;
3304 : : }
3305 : : /* e) compare non-tautomeric inverted to Inverted(isotopic tautomeric stereo) */
3306 [ # # ]: 0 : if (!eq2taut)
3307 : : {
3308 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
3309 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) &&
# # # # ]
3310 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3, 0 );
3311 : : /* stereo-inv isotopic non-taut = Inv(iso taut stereo) */
3312 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2INV | iiEq2ISO ) : 0;
3313 : : }
3314 : : /* f) compare non-tautomeric isotopic inverted to Inverted(non-tautomeric stereo) */
3315 [ # # ]: 0 : if (!eq2taut)
3316 : : {
3317 : 0 : eq2taut = pINChI && /* it is non-taut non-iso stereo */
3318 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
3319 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3, 0 );
3320 : : /* stereo-inv isotopic non-taut = Inv(non-taut stereo) */
3321 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2INV | iiEq2NONTAUT ) : 0;
3322 : : }
3323 : : /* g) compare non-tautomeric isotopic inverted to Inverted(non-tautomeric isotopic stereo) */
3324 [ # # ]: 0 : if (!eq2taut)
3325 : : {
3326 : 0 : eq2taut = pINChI && /* it is non-taut non-iso stereo */
3327 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) &&
# # ]
3328 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo, EQL_SP3, 0 );
3329 : : /* stereo-inv isotopic non-taut = Inv( iso non-taut stereo) */
3330 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2INV | iiEq2ISO | iiEq2NONTAUT ) : 0;
3331 : : }
3332 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
3333 : : if (!eq2taut && pINChI && !( ( Stereo = pINChI->StereoIsotopic ) &&
3334 : : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ) ))
3335 : : {
3336 : : /* component has no stereo; check whether it has stereo in the preceding layers */
3337 : : if (pINChI_Taut && ( Stereo_Taut = pINChI_Taut->Stereo ) && /* F is not empty */
3338 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ) ||
3339 : : !( pINChI_Taut && ( Stereo_Taut = pINChI_Taut->Stereo ) && /* M is empty and ... */
3340 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ) ) &&
3341 : : ( pINChI_Taut && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) && /* ... MI is not empty */
3342 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ) ))
3343 : : {
3344 : :
3345 : : eq2taut = iiEmpty; /* the component has stereo in the preceding layer */
3346 : : }
3347 : : }
3348 : : #endif
3349 : : }
3350 : : else
3351 : : {
3352 : : /*========= if not bSecondNonTautPass then compare inv taut stereo to various stereo ========*/
3353 [ # # # # : 0 : if (!bSecondNonTautPass && bOmitRepetitions && pINChI &&
# # ]
3354 [ # # ]: 0 : ( pINChI->nNumberOfIsotopicAtoms > 0 ||
3355 [ # # ]: 0 : pINChI->nNumberOfIsotopicTGroups > 0 ||
3356 [ # # # # ]: 0 : (pINChI->nPossibleLocationsOfIsotopicH && pINChI->nPossibleLocationsOfIsotopicH[0] > 1) )) /* djb-rwth: addressing LLVM warning */
3357 : : {
3358 : : /* compare tautomeric isotopic stereo-inverted to:
3359 : : * a) tautomeric stereo-inverted
3360 : : * b) Inverted(tautomeric stereo)
3361 : : * c) Inverted(tautomeric isotopic stereo)
3362 : : */
3363 : : /* a) compare tautomeric isotopic stereo-inverted to tautomeric stereo-inverted */
3364 [ # # ]: 0 : if (!eq2taut)
3365 : : {
3366 : 0 : eq2taut = pINChI &&
3367 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
3368 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
3369 : : /* stereo-inv isotopic taut = taut stereo-inv */
3370 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO ) : 0;
3371 : : }
3372 : : /* b) compare tautomeric isotopic stereo-inverted to Inverted(tautomeric stereo) */
3373 [ # # ]: 0 : if (!eq2taut)
3374 : : {
3375 : 0 : eq2taut = pINChI &&
3376 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
3377 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3, 0 );
3378 : : /* stereo-inv isotopic taut = Inv(taut stereo) */
3379 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiEq2INV ) : 0;
3380 : : }
3381 : : /* c) compare tautomeric isotopic stereo-inverted to Inverted(tautomeric isotopic stereo) */
3382 [ # # ]: 0 : if (!eq2taut)
3383 : : {
3384 : 0 : eq2taut = pINChI &&
3385 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) &&
# # ]
3386 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo, EQL_SP3, 0 );
3387 : : /* stereo-inv isotopic taut = Inv(taut iso stereo) */
3388 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiEq2INV | iiEq2ISO ) : 0;
3389 : : }
3390 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
3391 : : if (!eq2taut && pINChI && !( ( Stereo = pINChI->StereoIsotopic ) &&
3392 : : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ) ))
3393 : : {
3394 : : /* component has no MI stereo; check whether it has stereo in the preceding layer M */
3395 : : if (( Stereo_Taut = pINChI->Stereo ) &&
3396 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ))
3397 : : {
3398 : : eq2taut = iiEmpty; /* the component has stereo in the preceding layer */
3399 : : }
3400 : : }
3401 : : #endif
3402 : : }
3403 : : }
3404 [ # # ]: 0 : if (eq2taut)
3405 : : {
3406 : : /* we may be here only in case of the current layer found equal in another layer the same component */
3407 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
3408 : : {
3409 : : /* previous component exists; output it before output the current component */
3410 [ # # ]: 0 : if (bNext++)
3411 : : {
3412 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3413 : : }
3414 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->StereoIsotopic ) && Stereo_Prev->nNumberOfStereoCenters > 0)
3415 : : {
3416 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
3417 : :
3418 : 0 : MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parityInv,
3419 : : 0, Stereo_Prev->nNumberOfStereoCenters,
3420 : : strbuf, TAUT_MODE, bOverflow );
3421 : : }
3422 : : }
3423 : : else
3424 : : {
3425 [ # # # # ]: 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
3426 : : {
3427 : : /* previous non-taut component exists only in taut list */
3428 [ # # ]: 0 : if (bNext++)
3429 : : {
3430 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3431 : : }
3432 : : /* do not output stereo of non-tautomeric in non-taut layer: it has been output in the main layer */
3433 : : }
3434 : : }
3435 : : /* we have found another (previously printed) layer of the current component equal to this layer */
3436 : : /* output this (current) equivalence mark = EquString(eq2taut) */
3437 : 0 : pCurrEquStr = EquString( eq2taut );
3438 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3439 : : {
3440 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
3441 : : {
3442 : 0 : multPrevEquStr++;
3443 : : }
3444 : : else
3445 : : {
3446 : : /* new EqStr is different; output it */
3447 [ # # ]: 0 : if (bNext++)
3448 : : {
3449 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3450 : : }
3451 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3452 : 0 : pPrevEquStr = pCurrEquStr;
3453 : 0 : multPrevEquStr = 1;
3454 : : }
3455 : : }
3456 : : else
3457 : : {
3458 : 0 : pPrevEquStr = pCurrEquStr;
3459 : 0 : multPrevEquStr = 1;
3460 : : }
3461 : 0 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
3462 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
3463 : 0 : mult = 0;
3464 : 0 : eq2tautPrev = 1; /* pINChI_Prev and pINChI_Taut_Prev have already been output */
3465 : : }
3466 : : else
3467 : : {
3468 [ # # ]: 0 : if (eq2tautPrev)
3469 : : {
3470 : : /* at this point pINChI_Prev does not exist; however, pINChI */
3471 : : /*might have been discovered and it is different from pINChI_Taut */
3472 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3473 : : {
3474 : : /* new EqStr is different; output it */
3475 [ # # ]: 0 : if (bNext++)
3476 : : {
3477 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3478 : : }
3479 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3480 : 0 : pPrevEquStr = NULL;
3481 : 0 : multPrevEquStr = 0;
3482 : : }
3483 : 0 : eq2tautPrev = 0;
3484 : 0 : pINChI_Prev = pINChI;
3485 : 0 : pINChI_Taut_Prev = pINChI_Taut;
3486 : 0 : mult = 0;
3487 : : }
3488 : : else
3489 : : {
3490 : : /* current layer is different from previously printed layers of the current component */
3491 : : /* compare the current layer to this layer of the previous component: */
3492 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
3493 : : /*================ compare iso sp3 to previous =====================*/
3494 [ # # ]: 0 : eq2prev = bUseMulipliers &&
3495 [ # # # # ]: 0 : pINChI && pINChI->nNumberOfIsotopicAtoms + pINChI->nNumberOfIsotopicTGroups > 0 &&
3496 [ # # ]: 0 : pINChI_Prev && pINChI_Prev->nNumberOfIsotopicAtoms + pINChI_Prev->nNumberOfIsotopicTGroups > 0 &&
3497 : : /* do both have stereo? */
3498 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Prev = pINChI_Prev->StereoIsotopic ) &&
# # # # ]
3499 : : /* is their inverted stereo same? */
3500 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Prev, EQL_SP3_INV, 0 );
3501 [ # # ]: 0 : if (eq2prev)
3502 : : {
3503 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
3504 : 0 : continue;
3505 : : }
3506 : : else
3507 : : {
3508 [ # # ]: 0 : if (bNext++)
3509 : : {
3510 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3511 : : }
3512 [ # # # # : 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms && pINChI_Prev->nNumberOfIsotopicAtoms + pINChI_Prev->nNumberOfIsotopicTGroups > 0)
# # ]
3513 : : {
3514 [ # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->StereoIsotopic ) &&
3515 [ # # # # ]: 0 : Stereo_Prev->nNumberOfStereoCenters > 0 && Stereo_Prev->nCompInv2Abs)
3516 : : {
3517 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
3518 : :
3519 : 0 : MakeStereoString( Stereo_Prev->nNumberInv, NULL, Stereo_Prev->t_parityInv,
3520 : : 0, Stereo_Prev->nNumberOfStereoCenters,
3521 : : strbuf, TAUT_MODE, bOverflow );
3522 : : }
3523 : : /* else sp3 info is not present in pINChI_Prev */
3524 : : }
3525 : : else
3526 : : {
3527 : : /* do not print pINChI_Prev because it either do not exist of have already been printed */
3528 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
3529 : : {
3530 [ # # ]: 0 : if (( Stereo_Taut_Prev = pINChI_Taut_Prev->StereoIsotopic ) &&
3531 [ # # ]: 0 : Stereo_Taut_Prev->nNumberOfStereoCenters > 0 && Stereo_Taut_Prev->nCompInv2Abs)
3532 : : {
3533 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
3534 : : /* and it has non-trivial inv sp3 info. It has already been printed in the main section */
3535 : : /*
3536 : : tot_len += MakeDelim( sIdenticalValues, strbuf, bOverflow);
3537 : : */
3538 : : ;/* pINChI_Taut_Prev sp3 info was output in the main stereo section */
3539 : : }
3540 : : else
3541 : : {
3542 : : ; /* pINChI_Taut_Prev exists and has not sp3 info */
3543 : : }
3544 : : }
3545 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
3546 : : else
3547 : : {
3548 : : int stop = 1; /* <BRKPT> */
3549 : : }
3550 : : #endif
3551 : : }
3552 : : }
3553 : 0 : pINChI_Prev = pINChI;
3554 : 0 : mult = 0; /* we do not know whether the item is empty */
3555 : : }
3556 : : }
3557 : : }
3558 : :
3559 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
3560 : : }
3561 : :
3562 : :
3563 : : /****************************************************************************
3564 : : Produce isotopic tetr stereo inversion numbering substring of AuxInfo
3565 : : /iN: in Isotopic and/or FixedH-Iso parts,
3566 : : in both normal and in reconnected layers
3567 : : ****************************************************************************/
3568 : 0 : int str_AuxInvIsoSp3Numb( CANON_GLOBALS *pCG,
3569 : : INCHI_SORT *pINChISort,
3570 : : INCHI_SORT *pINChISort2,
3571 : : INCHI_IOS_STRING *strbuf,
3572 : : int *bOverflow,
3573 : : int bOutType,
3574 : : int TAUT_MODE,
3575 : : int num_components,
3576 : : int bSecondNonTautPass,
3577 : : int bOmitRepetitions )
3578 : : {
3579 : : int i, ii, ii2, nUsedLength0;
3580 : : INCHI_SORT *is, *is0 /*, *is2*/;
3581 : : INChI *pINChI, *pINChI_Taut;
3582 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Taut; /* djb-rwth: removing redundant variables */
3583 : : INChI_Stereo *Stereo, *Stereo_Taut;
3584 : : int eq2taut, bNext;
3585 : : const char *pPrevEquStr, *pCurrEquStr;
3586 : : int multPrevEquStr;
3587 : : /**************************************************
3588 : : * specificity of numbering: there is no previous *
3589 : : * component because no repetition is possible *
3590 : : **************************************************/
3591 : 0 : pINChI = NULL;
3592 : 0 : pINChI_Taut = NULL;
3593 : 0 : pINChI_Aux = NULL;
3594 : 0 : pINChI_Aux_Taut = NULL;
3595 : : /* djb-rwth: removing redundant code */
3596 : 0 : bNext = 0;
3597 : 0 : is = NULL;
3598 : : /* is2 = NULL;*/
3599 : 0 : is0 = pINChISort;
3600 : : /* is20 = bSecondNonTautPass? pINChISort2 : NULL;*/
3601 : : /* djb-rwth: removing redundant code */
3602 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
3603 : 0 : multPrevEquStr = 0;
3604 : 0 : nUsedLength0 = strbuf->nUsedLength;
3605 : :
3606 : : /* For each connected component... */
3607 [ # # ]: 0 : for (i = 0; i < num_components; i++)
3608 : : {
3609 : :
3610 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
3611 : 0 : is = is0 + i;
3612 [ # # # # : 0 : pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
3613 [ # # ]: 0 : pINChI_Aux = pINChI ? is->pINChI_Aux[ii] : NULL;
3614 : : /*================ to compare to previously printed =====================*/
3615 [ # # ]: 0 : if (bSecondNonTautPass)
3616 : : {
3617 : : /* component that was printed on the 1st pass */
3618 [ # # # # : 0 : pINChI_Taut = ( 0 <= ( ii2 = GET_II( OUT_T1, is ) ) ) ? is->pINChI[ii2] : NULL;
# # # # #
# ]
3619 [ # # ]: 0 : pINChI_Aux_Taut = pINChI_Taut ? is->pINChI_Aux[ii2] : NULL;
3620 : : }
3621 : 0 : eq2taut = 0;
3622 : : /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
3623 [ # # # # : 0 : if (bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Aux && pINChI_Aux->bIsIsotopic &&
# # # # #
# ]
3624 [ # # # # ]: 0 : ( Stereo = pINChI->StereoIsotopic ) && Stereo->nCompInv2Abs &&
3625 [ # # # # ]: 0 : pINChI_Aux->nNumberOfAtoms > 0 && pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv)
3626 : : {
3627 : : /* compare isotopic non-tautomeric inverted stereo numbering to:
3628 : : * a) tautomeric numbering
3629 : : * b) non-tautomeric numbering
3630 : : * c) *tautomeric isotopic numbering
3631 : : * d) *non-tautomeric isotopic numbering
3632 : : * e) tautomeric inverted stereo numbering
3633 : : * f) *non-tautomeric inverted stereo numbering
3634 : : * g) tautomeric isotopic inverted stereo numbering
3635 : : */
3636 : : /* a) compare isotopic non-tautomeric inverted stereo numbering to tautomeric numbering */
3637 [ # # ]: 0 : if (!eq2taut)
3638 : : {
3639 [ # # # # ]: 0 : eq2taut = pINChI_Taut &&
3640 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM );
3641 : : /* stereo-inv isotopic numbering non-taut = taut numbering */
3642 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT ) : 0;
3643 : : }
3644 : : /* b) compare isotopic non-tautomeric inverted stereo numbering to non-tautomeric numbering */
3645 [ # # ]: 0 : if (!eq2taut)
3646 : : {
3647 : : eq2taut =
3648 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM );
3649 : : /* stereo-inv isotopic numb. non-taut = non-taut numbering */
3650 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2NONTAUT ) : 0;
3651 : : }
3652 : : /* c) compare isotopic non-tautomeric inverted stereo numbering to tautomeric isotopic numbering */
3653 [ # # ]: 0 : if (!eq2taut)
3654 : : {
3655 [ # # # # ]: 0 : eq2taut = pINChI_Taut &&
3656 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM_ISO );
3657 : : /* stereo-inv isotopic numb. non-taut = taut iso numbering */
3658 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2ISO ) : 0;
3659 : : }
3660 : : /* d) compare isotopic non-tautomeric inverted stereo numbering to non-tautomeric isotopic numbering */
3661 [ # # ]: 0 : if (!eq2taut)
3662 : : {
3663 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM_ISO );
3664 : : /* stereo-inv isotopic numb. non-taut = non-taut isotopic numbering */
3665 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2NONTAUT | iiEq2ISO ) : 0;
3666 : : }
3667 : : /* e) compare isotopic non-tautomeric inverted stereo numbering to tautomeric inverted stereo numbering */
3668 [ # # ]: 0 : if (!eq2taut)
3669 : : {
3670 [ # # ]: 0 : eq2taut = pINChI_Taut && pINChI_Aux_Taut &&
3671 [ # # # # : 0 : ( Stereo_Taut = pINChI_Taut->Stereo ) && Stereo_Taut->nCompInv2Abs &&
# # # # ]
3672 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM_INV );
3673 : : /* stereo-inv isotopic numbering non-taut = stereo-inv taut numbering */
3674 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2INV ) : 0;
3675 : : }
3676 : : /* f) compare isotopic non-tautomeric inverted stereo numbering to non-tautomeric inverted stereo numbering */
3677 [ # # ]: 0 : if (!eq2taut)
3678 : : {
3679 : 0 : eq2taut =
3680 [ # # # # : 0 : ( Stereo_Taut = pINChI->StereoIsotopic ) && Stereo_Taut->nCompInv2Abs &&
# # ]
3681 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM_INV );
3682 : : /* stereo-inv isotopic numbering non-taut = stereo-inv non-taut numbering */
3683 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2INV | iiEq2NONTAUT ) : 0;
3684 : : }
3685 : :
3686 : : /* g) compare isotopic non-tautomeric inverted stereo numbering to tautomeric isotopic inverted stereo numbering */
3687 [ # # ]: 0 : if (!eq2taut)
3688 : : {
3689 : 0 : eq2taut = pINChI_Taut &&
3690 [ # # # # : 0 : ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) && Stereo_Taut->nCompInv2Abs &&
# # # # ]
3691 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM_INV | EQL_NUM_ISO );
3692 : : /* stereo-inv isotopic numbering non-taut = stereo-inv iso taut numbering */
3693 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2INV | iiEq2ISO ) : 0;
3694 : : }
3695 : : }
3696 : : else
3697 : : {
3698 : : /*========= if not bSecondNonTautPass then compare inv taut stereo numb to taut numb ========*/
3699 [ # # # # : 0 : if (!bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Aux && pINChI_Aux->bIsIsotopic &&
# # # # #
# ]
3700 [ # # # # ]: 0 : ( Stereo = pINChI->StereoIsotopic ) && Stereo->nCompInv2Abs &&
3701 [ # # # # ]: 0 : pINChI_Aux->nNumberOfAtoms > 0 && pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv)
3702 : : {
3703 : : /* compare isotopic tautomeric inverted stereo numbering to:
3704 : : * a) tautomeric numbering
3705 : : * b) tautomeric isotopic numbering
3706 : : * c) tautomeric inverted stereo numbering
3707 : : */
3708 : : /* a) compare isotopic tautomeric inverted stereo numbering to tautomeric numbering */
3709 [ # # ]: 0 : if (!eq2taut)
3710 : : {
3711 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM );
3712 : : /* stereo-inv isotopic numbering (taut) = taut numbering */
3713 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB ) : 0;
3714 : : }
3715 : : /* b) compare isotopic tautomeric inverted stereo numbering to tautomeric isotopic numbering */
3716 [ # # ]: 0 : if (!eq2taut)
3717 : : {
3718 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM_ISO );
3719 : : /* stereo-inv isotopic numbering(taut) = isotopic taut numbering */
3720 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iiEq2ISO ) : 0;
3721 : : }
3722 : : /* b) compare isotopic tautomeric inverted stereo numbering to tautomeric inverted stereo numbering */
3723 [ # # ]: 0 : if (!eq2taut)
3724 : : {
3725 [ # # # # : 0 : eq2taut = pINChI->Stereo && Stereo->nCompInv2Abs &&
# # ]
3726 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM_INV ); /* djb-rwth: removing redundant code */
3727 : : /* stereo-inv isotopic numbering (taut) = taut stereo-inv numbering */
3728 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iiEq2INV ) : 0;
3729 : : }
3730 : : }
3731 : : }
3732 [ # # ]: 0 : if (eq2taut)
3733 : : {
3734 : : /* we have found another (previously printed) layer of the current component equal to this layer */
3735 : : /* output this (current) equivalence mark = EquString(eq2taut) */
3736 : 0 : pCurrEquStr = EquString( eq2taut );
3737 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3738 : : {
3739 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
3740 : : {
3741 : 0 : multPrevEquStr++;
3742 : : }
3743 : : else
3744 : : {
3745 : : /* new EqStr is different; output it */
3746 [ # # ]: 0 : if (bNext++)
3747 : : {
3748 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3749 : : }
3750 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3751 : 0 : pPrevEquStr = pCurrEquStr;
3752 : 0 : multPrevEquStr = 1;
3753 : : }
3754 : : }
3755 : : else
3756 : : {
3757 : 0 : pPrevEquStr = pCurrEquStr;
3758 : 0 : multPrevEquStr = 1;
3759 : : }
3760 : : }
3761 : : else
3762 : : {
3763 : : /* current layer is different from previously printed layers of the current component */
3764 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3765 : : {
3766 : : /* new EqStr is different; output it */
3767 [ # # ]: 0 : if (bNext++)
3768 : : {
3769 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3770 : : }
3771 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3772 : 0 : pPrevEquStr = NULL;
3773 : 0 : multPrevEquStr = 0;
3774 : : }
3775 [ # # ]: 0 : if (bNext++)
3776 : : {
3777 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3778 : : }
3779 [ # # # # : 0 : if (pINChI && pINChI_Aux && pINChI_Aux->bIsIsotopic && pINChI_Aux->nNumberOfAtoms &&
# # # # ]
3780 [ # # # # ]: 0 : ( Stereo = pINChI->StereoIsotopic ) && Stereo->nNumberOfStereoCenters &&
3781 [ # # # # ]: 0 : Stereo->nCompInv2Abs && pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv)
3782 : : {
3783 : 0 : MakeCtString( pCG, pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv,
3784 : : pINChI_Aux->nNumberOfAtoms, 0, NULL, 0,
3785 : : strbuf, TAUT_MODE, bOverflow );
3786 : : }
3787 : : /* else isotopic inv stereo info is not present in pINChI */
3788 : : }
3789 : : }
3790 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3791 : : {
3792 : : /* the new EqStr of the last item has not been printed; output it now */
3793 [ # # ]: 0 : if (bNext++)
3794 : : {
3795 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3796 : : }
3797 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3798 : 0 : pPrevEquStr = NULL;
3799 : : /* djb-rwth: removing redundant code */
3800 : : }
3801 : :
3802 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
3803 : : }
3804 : :
3805 : :
3806 : : /****************************************************************************
3807 : : Produce numbering substring of AuxInfo
3808 : : /N: in Main and/or /F: in FixedH part,
3809 : : in both normal and in reconnected layers
3810 : : ****************************************************************************/
3811 : 124 : int str_AuxNumb( CANON_GLOBALS *pCG,
3812 : : INCHI_SORT *pINChISort,
3813 : : INCHI_SORT *pINChISort2,
3814 : : INCHI_IOS_STRING *strbuf,
3815 : : int *bOverflow,
3816 : : int bOutType,
3817 : : int TAUT_MODE,
3818 : : int num_components,
3819 : : int bSecondNonTautPass,
3820 : : int bOmitRepetitions )
3821 : : {
3822 : : int i, ii, ii2, nUsedLength0;
3823 : : INCHI_SORT *is, *is0 /*, *is2*/;
3824 : 124 : INChI *pINChI, *pINChI_Taut = NULL;
3825 : 124 : INChI_Aux *pINChI_Aux, *pINChI_Aux_Taut = NULL;
3826 : : int eq2taut, bNext;
3827 : : const char *pPrevEquStr, *pCurrEquStr;
3828 : : int multPrevEquStr;
3829 : 124 : bNext = 0;
3830 : : /*is2 = bSecondNonTautPass? pINChISort2 : NULL;*/
3831 : : /* djb-rwth: removing redundant code */
3832 : 124 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
3833 : 124 : multPrevEquStr = 0;
3834 : 124 : is = NULL;
3835 : 124 : nUsedLength0 = strbuf->nUsedLength;
3836 : :
3837 [ - + ]: 124 : if (!( is0 = pINChISort ))
3838 : : {
3839 : 0 : return nUsedLength0;
3840 : : }
3841 : :
3842 : : /* For each connected component... */
3843 [ + + ]: 287 : for (i = 0; i < num_components; i++)
3844 : : {
3845 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
3846 : 163 : is = is0 + i;
3847 [ - + - - : 163 : pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
3848 [ + - ]: 163 : pINChI_Aux = pINChI ? is->pINChI_Aux[ii] : NULL;
3849 : : /*================ to compare to previously printed =====================*/
3850 [ - + ]: 163 : if (bSecondNonTautPass)
3851 : : {
3852 : : /* component that was printed on the 1st pass */
3853 [ # # # # : 0 : pINChI_Taut = ( 0 <= ( ii2 = GET_II( OUT_T1, is ) ) ) ? is->pINChI[ii2] : NULL;
# # # # #
# ]
3854 [ # # ]: 0 : pINChI_Aux_Taut = pINChI_Taut ? is->pINChI_Aux[ii2] : NULL;
3855 : : }
3856 : 163 : eq2taut = 0;
3857 : : /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
3858 [ - + - - : 163 : if (bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Aux && pINChI_Aux->nNumberOfAtoms > 0)
- - - - -
- ]
3859 : : {
3860 : : /* compare non-tautomeric numbering to:
3861 : : * a) tautomeric numbering
3862 : : */
3863 : : /* a) compare non-tautomeric numbering to tautomeric numbering */
3864 [ # # ]: 0 : if (!eq2taut)
3865 : : {
3866 [ # # # # : 0 : eq2taut = pINChI_Taut && !pINChI_Taut->bDeleted &&
# # ]
3867 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM, pINChI_Aux_Taut, EQL_NUM );
3868 : : /* numbering non-taut = taut numbering */
3869 [ # # ]: 0 : eq2taut = eq2taut ? ( iiNUMB | iitNONTAUT ) : 0;
3870 : : }
3871 : : }
3872 [ - + ]: 163 : if (eq2taut)
3873 : : {
3874 : : /* we have found another (previously printed) layer of the current component equal to this layer */
3875 : : /* output this (current) equivalence mark = EquString(eq2taut) */
3876 : 0 : pCurrEquStr = EquString( eq2taut );
3877 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3878 : : {
3879 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
3880 : : {
3881 : 0 : multPrevEquStr++;
3882 : : }
3883 : : else
3884 : : {
3885 : : /* new EqStr is different; output it */
3886 [ # # ]: 0 : if (bNext++)
3887 : : {
3888 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3889 : : }
3890 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3891 : 0 : pPrevEquStr = pCurrEquStr;
3892 : 0 : multPrevEquStr = 1;
3893 : : }
3894 : : }
3895 : : else
3896 : : {
3897 : 0 : pPrevEquStr = pCurrEquStr;
3898 : 0 : multPrevEquStr = 1;
3899 : : }
3900 : : }
3901 : : else
3902 : : {
3903 : : /* current layer is different from previously printed layers of the current component */
3904 [ - + - - ]: 163 : if (multPrevEquStr && pPrevEquStr)
3905 : : {
3906 : : /* new EqStr is different; output it */
3907 [ # # ]: 0 : if (bNext++)
3908 : : {
3909 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3910 : : }
3911 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3912 : 0 : pPrevEquStr = NULL;
3913 : 0 : multPrevEquStr = 0;
3914 : : }
3915 [ + + ]: 163 : if (bNext++)
3916 : : {
3917 : 39 : MakeDelim( sCompDelim, strbuf, bOverflow );
3918 : : }
3919 [ + - + - : 163 : if (pINChI && pINChI_Aux && pINChI_Aux->nNumberOfAtoms)
+ - ]
3920 : : {
3921 : 163 : MakeCtString( pCG, pINChI_Aux->nOrigAtNosInCanonOrd,
3922 : : pINChI_Aux->nNumberOfAtoms, 0, NULL, 0,
3923 : : strbuf, TAUT_MODE, bOverflow );
3924 : : }
3925 : : }
3926 : : }
3927 [ - + - - ]: 124 : if (multPrevEquStr && pPrevEquStr)
3928 : : {
3929 : : /* the new EqStr of the last item has not been printed; output it now */
3930 [ # # ]: 0 : if (bNext++)
3931 : : {
3932 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3933 : : }
3934 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3935 : 0 : pPrevEquStr = NULL;
3936 : : /* djb-rwth: removing redundant code */
3937 : : }
3938 : :
3939 : 124 : return ( strbuf->nUsedLength - nUsedLength0 );
3940 : : }
3941 : :
3942 : :
3943 : : /****************************************************************************
3944 : : Produce TGroup equivalence substring of AuxInfo
3945 : : ****************************************************************************/
3946 : 2 : int str_AuxTgroupEqu( INCHI_SORT *pINChISort,
3947 : : INCHI_IOS_STRING *strbuf,
3948 : : int *bOverflow,
3949 : : int bOutType,
3950 : : int TAUT_MODE,
3951 : : int num_components,
3952 : : int bUseMulipliers )
3953 : : {
3954 : : int i, ii, nUsedLength0;
3955 : : INCHI_SORT *is, *is0;
3956 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev;
3957 : : int mult, eq2prev, bNext;
3958 : :
3959 : 2 : nUsedLength0 = strbuf->nUsedLength;
3960 : :
3961 : 2 : is0 = pINChISort;
3962 : 2 : is = NULL;
3963 : 2 : i = 0;
3964 [ - + - - : 2 : pINChI_Aux_Prev = ( 0 <= ( ii = GET_II( bOutType, is0 ) ) ) ? is0->pINChI_Aux[ii] : NULL;
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
3965 : 2 : mult = 0;
3966 : 2 : bNext = 0;
3967 : :
3968 : : /* For each connected component... */
3969 [ + + ]: 9 : for (i++; i <= num_components; i++)
3970 : : {
3971 [ + + - + : 7 : pINChI_Aux = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI_Aux[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
3972 [ + - + + ]: 14 : eq2prev = bUseMulipliers &&
3973 : 7 : Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_TG, pINChI_Aux_Prev, EQL_EQU_TG );
3974 [ + + ]: 7 : if (eq2prev)
3975 : : {
3976 : 1 : mult++; /* mult = (number of non-empty equal items)-1 */
3977 : 1 : continue;
3978 : : }
3979 : : else
3980 : : {
3981 [ + + ]: 6 : if (bNext++)
3982 : : {
3983 : 4 : MakeDelim( sCompDelim, strbuf, bOverflow );
3984 : : }
3985 [ + - + + : 8 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfTGroups &&
+ - ]
3986 : 2 : bHasEquString( pINChI_Aux_Prev->nConstitEquTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups ))
3987 : : {
3988 : 2 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
3989 : 2 : MakeEquString( pINChI_Aux_Prev->nConstitEquTGroupNumbers,
3990 : : pINChI_Aux_Prev->nNumberOfTGroups,
3991 : : 0, strbuf,
3992 : : TAUT_MODE, bOverflow );
3993 : : }
3994 : : }
3995 : 6 : pINChI_Aux_Prev = pINChI_Aux;
3996 : 6 : mult = 0; /* we do not know whether the item is empty */
3997 : : }
3998 : :
3999 : 2 : return ( strbuf->nUsedLength - nUsedLength0 );
4000 : : }
4001 : :
4002 : :
4003 : : /****************************************************************************
4004 : : Produce charge-radical-valence substring of AuxInfo
4005 : : ****************************************************************************/
4006 : 11 : int str_AuxChargeRadVal( INCHI_SORT *pINChISort,
4007 : : INCHI_IOS_STRING *strbuf,
4008 : : int *bOverflow,
4009 : : int bOutType,
4010 : : int TAUT_MODE,
4011 : : int num_components,
4012 : : int bUseMulipliers )
4013 : : {
4014 : : int i, ii, nUsedLength0;
4015 : : INCHI_SORT *is, *is0;
4016 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev;
4017 : : int mult, eq2prev, bNext;
4018 : :
4019 : 11 : pINChI_Aux_Prev = NULL;
4020 : 11 : mult = 0;
4021 : 11 : bNext = 0;
4022 : 11 : is = NULL;
4023 : 11 : is0 = pINChISort;
4024 : 11 : nUsedLength0 = strbuf->nUsedLength;
4025 : :
4026 : : /* For each connected component... */
4027 [ + + ]: 43 : for (i = 0; i <= num_components; i++)
4028 : : {
4029 : :
4030 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
4031 [ + + - + : 32 : pINChI_Aux = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI_Aux[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
4032 : : /* check whether pINChI_Aux and pINChI_Aux_Prev have identical info */
4033 [ + - - + ]: 64 : eq2prev = bUseMulipliers &&
4034 : 32 : EqlOrigInfo( pINChI_Aux, pINChI_Aux_Prev );
4035 [ - + ]: 32 : if (eq2prev)
4036 : : {
4037 : : /* eq. info is same and non-trivial */
4038 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
4039 : 0 : continue;
4040 : : }
4041 : : else
4042 : : {
4043 [ + + ]: 32 : if (i)
4044 : : {
4045 : : /* pINChI_Aux info is either different or trivial. Output pINChI_Aux_Prev anyway */
4046 [ + + ]: 21 : if (bNext++)
4047 : : {
4048 : 10 : MakeDelim( sCompDelim, strbuf, bOverflow );
4049 : : }
4050 [ + - + - ]: 21 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
4051 : : {
4052 [ + + ]: 21 : if (bHasOrigInfo( pINChI_Aux_Prev->OrigInfo, pINChI_Aux_Prev->nNumberOfAtoms ))
4053 : : {
4054 : : /* pINChI_Aux_Prev exists and has orig. info info */
4055 : 12 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
4056 : 12 : MakeCRVString( pINChI_Aux_Prev->OrigInfo,
4057 : : pINChI_Aux_Prev->nNumberOfAtoms,
4058 : : 0, strbuf, TAUT_MODE, bOverflow );
4059 : : }
4060 : : else
4061 : : {
4062 : : ; /* pINChI_Aux_Prev exists and has only trivial info */
4063 : : }
4064 : : }
4065 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
4066 : : else
4067 : : {
4068 : : int stop = 1; /* <BRKPT> */
4069 : : }
4070 : : #endif
4071 : : }
4072 : : }
4073 : 32 : pINChI_Aux_Prev = pINChI_Aux;
4074 : 32 : mult = 0; /* we do not know whether the item is empty */
4075 : : }
4076 : :
4077 : 11 : return ( strbuf->nUsedLength - nUsedLength0 );
4078 : : }
4079 : :
4080 : :
4081 : : /****************************************************************************
4082 : : Prepare tautomeric transposition substring of AuxInfo
4083 : : ****************************************************************************/
4084 : 0 : int bin_AuxTautTrans( INCHI_SORT *pINChISort,
4085 : : INCHI_SORT *pINChISort2,
4086 : : AT_NUMB **pTrans_n,
4087 : : AT_NUMB **pTrans_s,
4088 : : int bOutType,
4089 : : int num_components )
4090 : : {
4091 : 0 : int i, ii, ii2, ret = 0;
4092 : : INCHI_SORT *is, *is2, *is0, *is20;
4093 : : INChI *pINChI, *pINChI_Taut;
4094 : 0 : AT_NUMB *nTrans_n = NULL;
4095 : 0 : AT_NUMB *nTrans_s = NULL;
4096 : :
4097 : : /* djb-rwth: removing redundant code */
4098 : 0 : is0 = pINChISort;
4099 : 0 : is20 = pINChISort2;
4100 : :
4101 : : /* djb-rwth: rewritten to avoid memory leaks -- updated 25/09/2025 */
4102 : :
4103 : : /* Pass 1: save new non-taut numbering */
4104 : : /* For each connected component... */
4105 [ # # ]: 0 : for (i = 0; i < num_components; i++)
4106 : : {
4107 : 0 : is = is0 + i;
4108 : 0 : is2 = is20 + i;
4109 [ # # # # : 0 : pINChI = (0 <= (ii = GET_II(bOutType, is))) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
4110 [ # # # # : 0 : pINChI_Taut = (0 <= (ii2 = GET_II(OUT_T1, is2))) ? is2->pINChI[ii2] : NULL;
# # # # #
# ]
4111 [ # # # # : 0 : if (pINChI && pINChI->nNumberOfAtoms > 0 &&
# # ]
4112 [ # # ]: 0 : pINChI_Taut && pINChI_Taut->nNumberOfAtoms > 0 &&
4113 : : /* different components save equal new ord. numbers: */
4114 [ # # ]: 0 : is->ord_number != is2->ord_number)
4115 : : {
4116 [ # # ]: 0 : if (!nTrans_n)
4117 : : {
4118 : 0 : nTrans_n = (AT_NUMB*)inchi_calloc((long long)num_components + 1, sizeof(nTrans_n[0]));
4119 : : }
4120 [ # # ]: 0 : if (!nTrans_s)
4121 : : {
4122 : 0 : nTrans_s = (AT_NUMB*)inchi_calloc((long long)num_components + 1, sizeof(nTrans_s[0]));
4123 : : }
4124 [ # # # # ]: 0 : if (nTrans_n && nTrans_s)
4125 : : {
4126 : : /* new ordering number for original non-tautomeric component number is->ord_number */
4127 : 0 : nTrans_n[is->ord_number] = i + 1; /*nTrans_t[is2->ord_number] =*/
4128 : : }
4129 : : }
4130 : : }
4131 [ # # # # ]: 0 : if (nTrans_n && nTrans_s)
4132 : : {
4133 : : /* Pass 2: get new taut numbering, retrieve new non-taut and save the transposition */
4134 [ # # ]: 0 : for (i = 0; i < num_components; i++)
4135 : : {
4136 : 0 : is = is0 + i;
4137 : 0 : is2 = is20 + i;
4138 [ # # # # : 0 : pINChI = (0 <= (ii = GET_II(bOutType, is))) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
4139 [ # # # # : 0 : pINChI_Taut = (0 <= (ii2 = GET_II(OUT_T1, is2))) ? is2->pINChI[ii2] : NULL;
# # # # #
# ]
4140 [ # # # # : 0 : if (pINChI && pINChI->nNumberOfAtoms > 0 &&
# # ]
4141 [ # # ]: 0 : pINChI_Taut && pINChI_Taut->nNumberOfAtoms > 0 &&
4142 [ # # ]: 0 : is->ord_number != is2->ord_number &&
4143 [ # # ]: 0 : nTrans_n[is2->ord_number])
4144 : : {
4145 : : /* nTrans_n[is2->ord_number] is new ordering number of
4146 : : the non-taut representation of the tautomeric component
4147 : : that has new ord number i+1 and orig ordering number is2->ord_number.
4148 : : Old numbers start from 0, new start from 1
4149 : : */
4150 : :
4151 : : /* n = nTrans_s[t]: taut component #t is in position #n of the non-taut representation */
4152 : 0 : nTrans_s[i + 1] = nTrans_n[is2->ord_number];
4153 : : }
4154 : : }
4155 : 0 : *pTrans_n = nTrans_n;
4156 : 0 : *pTrans_s = nTrans_s;
4157 : 0 : ret = 1;
4158 : : }
4159 : : else
4160 : : {
4161 [ # # ]: 0 : if (nTrans_n)
4162 : : {
4163 [ # # ]: 0 : inchi_free(nTrans_n);
4164 : 0 : ret = -1;
4165 : : }
4166 [ # # ]: 0 : if (nTrans_s)
4167 : : {
4168 [ # # ]: 0 : inchi_free(nTrans_s);
4169 : 0 : ret = -1;
4170 : : }
4171 : : }
4172 : :
4173 : 0 : return ret;
4174 : : }
4175 : :
4176 : :
4177 : : /****************************************************************************
4178 : : Output tautomeric transposition substring of AuxInfo
4179 : : ****************************************************************************/
4180 : 0 : int str_AuxTautTrans( CANON_GLOBALS *pCG,
4181 : : AT_NUMB *nTrans_n,
4182 : : AT_NUMB *nTrans_s,
4183 : : INCHI_IOS_STRING *strbuf,
4184 : : int *bOverflow,
4185 : : int TAUT_MODE,
4186 : : int num_components )
4187 : : {
4188 : : int i, k, len, j, nUsedLength0;
4189 : :
4190 : 0 : nUsedLength0 = strbuf->nUsedLength;
4191 : :
4192 [ # # # # ]: 0 : if (nTrans_n && nTrans_s)
4193 : : {
4194 : : /* print the transposition, cycle after cycle */
4195 [ # # ]: 0 : for (i = 1; i <= num_components; i++)
4196 : : {
4197 [ # # ]: 0 : if (nTrans_s[i])
4198 : : {
4199 : : /* get one cycle of the transposition */
4200 [ # # ]: 0 : for (j = i, len = 0; ( k = nTrans_s[j] ); j = k, len++)
4201 : : {
4202 : 0 : nTrans_n[len] = j; /* save the transposition */
4203 : 0 : nTrans_s[j] = 0; /* clear used element to avoid repetitions */
4204 : : }
4205 : : /* print one cycle of the transposition */
4206 : 0 : MakeDelim( "(", strbuf, bOverflow );
4207 : 0 : MakeCtString( pCG, nTrans_n, len, 0, NULL, 0,
4208 : : strbuf, TAUT_MODE, bOverflow );
4209 : 0 : MakeDelim( ")", strbuf, bOverflow );
4210 : : }
4211 : : }
4212 : : }
4213 [ # # ]: 0 : if (nTrans_n)
4214 : : {
4215 [ # # ]: 0 : inchi_free( nTrans_n );
4216 : : }
4217 [ # # ]: 0 : if (nTrans_s)
4218 : : {
4219 [ # # ]: 0 : inchi_free( nTrans_s );
4220 : : }
4221 : :
4222 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
4223 : : }
4224 : :
4225 : :
4226 : : /****************************************************************************
4227 : : Output isotopic TGroup equivalence substring of AuxInfo
4228 : : ****************************************************************************/
4229 : 0 : int str_AuxIsoTgroupEqu( INCHI_SORT *pINChISort,
4230 : : INCHI_IOS_STRING *strbuf,
4231 : : int *bOverflow,
4232 : : int bOutType,
4233 : : int TAUT_MODE,
4234 : : int num_components,
4235 : : int bOmitRepetitions,
4236 : : int bUseMulipliers )
4237 : : {
4238 : : int i, ii, nUsedLength0;
4239 : : INCHI_SORT *is, *is0;
4240 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev;
4241 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
4242 : : const char *pPrevEquStr, *pCurrEquStr;
4243 : : int multPrevEquStr;
4244 : 0 : pINChI_Aux = NULL;
4245 : 0 : pINChI_Aux_Prev = NULL;
4246 : 0 : mult = 0;
4247 : 0 : bNext = 0;
4248 : 0 : is = NULL;
4249 : 0 : is0 = pINChISort;
4250 : : /* djb-rwth: removing redundant code */
4251 : 0 : eq2tautPrev = 1; /* pINChI_Aux_Prev (previous pINChI_Aux) does not exist */
4252 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
4253 : 0 : multPrevEquStr = 0;
4254 : 0 : nUsedLength0 = strbuf->nUsedLength;
4255 : :
4256 : : /* For each connected component... */
4257 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
4258 : : {
4259 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
4260 [ # # # # : 0 : pINChI_Aux = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI_Aux[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
4261 : : /*================ compare iso non-taut equivalence info to non-iso taut ========*/
4262 : 0 : eq2taut = 0;
4263 [ # # # # : 0 : if (bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic)
# # ]
4264 : : {
4265 : : /**************************************************
4266 : : * compare isotopic tautomeric equivalence to:
4267 : : * a) non-isotopic tautomeric
4268 : : */
4269 : : /* compare isotopic t-group equivalence to non-isotopic */
4270 : 0 : eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_TG | EQL_EQU_ISO, pINChI_Aux, EQL_EQU_TG );
4271 : : /* equ taut-isotopic = tautomeric, same as for isotopic atom equivalence info*/
4272 [ # # ]: 0 : eq2taut = eq2taut ? ( iiEQU | iitISO ) : 0;
4273 : : }
4274 [ # # ]: 0 : if (eq2taut)
4275 : : {
4276 : : /* current isotopic t-group equivalence has been found to be same as non-isotopic */
4277 [ # # # # ]: 0 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
4278 : : {
4279 : : /* previous component exists */
4280 [ # # ]: 0 : if (bNext++)
4281 : : {
4282 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
4283 : : }
4284 [ # # ]: 0 : if (bHasEquString( pINChI_Aux_Prev->nConstitEquIsotopicTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups ))
4285 : : {
4286 : : /* output previous component(s) equivalence since it was found to be non-trivial */
4287 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
4288 : 0 : MakeEquString( pINChI_Aux_Prev->nConstitEquIsotopicTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups, 0,
4289 : : strbuf, TAUT_MODE, bOverflow );
4290 : : }
4291 : : else
4292 : : {
4293 : : ; /* pINChI_Aux_Prev exists and does not have non-trivial t-group equivalence info */
4294 : : }
4295 : : }
4296 : : /* we have found pINChI_Aux->pINChI_Aux->nConstitEquIsotopicTGroupNumbers same as in pINChI_Aux->nConstitEquTGroupNumbers */
4297 : 0 : pCurrEquStr = EquString( eq2taut );
4298 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
4299 : : {
4300 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
4301 : : {
4302 : 0 : multPrevEquStr++;
4303 : : }
4304 : : else
4305 : : {
4306 : : /* new EqStr is different; output it */
4307 [ # # ]: 0 : if (bNext++)
4308 : : {
4309 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
4310 : : }
4311 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
4312 : 0 : pPrevEquStr = pCurrEquStr;
4313 : 0 : multPrevEquStr = 1;
4314 : : }
4315 : : }
4316 : : else
4317 : : {
4318 : 0 : pPrevEquStr = pCurrEquStr;
4319 : 0 : multPrevEquStr = 1;
4320 : : }
4321 : 0 : pINChI_Aux_Prev = NULL; /* pINChI_Aux_Prev has already been output */
4322 : 0 : mult = 0;
4323 : 0 : eq2tautPrev = 1;
4324 : : }
4325 : : else
4326 : : {
4327 [ # # ]: 0 : if (eq2tautPrev)
4328 : : {
4329 : : /* at this point pINChI_Aux_Prev does not exist; however, pINChI_Aux */
4330 : : /* might have been discovered and it may be different from non-isotopic */
4331 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
4332 : : {
4333 : : /* new EqStr is different; output it */
4334 [ # # ]: 0 : if (bNext++)
4335 : : {
4336 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
4337 : : }
4338 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
4339 : 0 : pPrevEquStr = NULL;
4340 : 0 : multPrevEquStr = 0;
4341 : : }
4342 : 0 : eq2tautPrev = 0;
4343 : 0 : pINChI_Aux_Prev = pINChI_Aux;
4344 : 0 : mult = 0;
4345 : : }
4346 : : else
4347 : : {
4348 : : /* check whether pINChI_Aux and pINChI_Aux_Prev have identical non-trivial isotopic t-group equivalence info */
4349 [ # # # # ]: 0 : eq2prev = bUseMulipliers && Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_TG | EQL_EQU_ISO, pINChI_Aux_Prev, EQL_EQU_TG | EQL_EQU_ISO );
4350 [ # # ]: 0 : if (eq2prev)
4351 : : {
4352 : : /* eq. info is same and non-trivial */
4353 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
4354 : 0 : continue;
4355 : : }
4356 : : else
4357 : : {
4358 : : /* pINChI_Aux eq. info is either different or trivial. Output pINChI_Aux_Prev anyway */
4359 [ # # ]: 0 : if (bNext++)
4360 : : {
4361 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
4362 : : }
4363 [ # # # # ]: 0 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
4364 : : {
4365 [ # # ]: 0 : if (bHasEquString( pINChI_Aux_Prev->nConstitEquIsotopicTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups ))
4366 : : {
4367 : : /* pINChI_Aux_Prev exists and has equivalence info */
4368 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
4369 : 0 : MakeEquString( pINChI_Aux_Prev->nConstitEquIsotopicTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups, 0,
4370 : : strbuf, TAUT_MODE, bOverflow );
4371 : : }
4372 : : else
4373 : : {
4374 : : ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
4375 : : }
4376 : : }
4377 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
4378 : : else
4379 : : {
4380 : : int stop = 1; /* <BRKPT> */
4381 : : }
4382 : : #endif
4383 : : }
4384 : 0 : pINChI_Aux_Prev = pINChI_Aux;
4385 : 0 : mult = 0; /* we do not know whether the item is empty */
4386 : : }
4387 : : }
4388 : : }
4389 : :
4390 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
4391 : : }
|